/* 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
+ 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;
static void import_export_class (tree);
static tree get_guard_bits (tree);
static void determine_visibility_from_class (tree, tree);
+static bool decl_defined_p (tree);
/* A list of static class variables. This is needed, because a
static class variable can be declared inside the class without
may need to emit outline anyway. */
static GTY(()) VEC(tree,gc) *deferred_fns;
+/* A list of decls that use types with no linkage, which we need to make
+ sure are defined. */
+static GTY(()) VEC(tree,gc) *no_linkage_decls;
+
/* Nonzero if we're done parsing and into end-of-file activities. */
int at_eof;
build_memfn_type (tree fntype, tree ctype, cp_cv_quals quals)
{
tree raises;
+ tree attrs;
int type_quals;
if (fntype == error_mark_node || ctype == error_mark_node)
return error_mark_node;
+ gcc_assert (TREE_CODE (fntype) == FUNCTION_TYPE
+ || TREE_CODE (fntype) == METHOD_TYPE);
+
type_quals = quals & ~TYPE_QUAL_RESTRICT;
ctype = cp_build_qualified_type (ctype, type_quals);
+ raises = TYPE_RAISES_EXCEPTIONS (fntype);
+ attrs = TYPE_ATTRIBUTES (fntype);
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);
+ if (attrs)
+ fntype = cp_build_type_attribute_variant (fntype, attrs);
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. */
tree
cp_build_parm_decl (tree name, tree type)
{
- tree parm = build_decl (PARM_DECL, name, type);
+ tree parm = build_decl (input_location,
+ PARM_DECL, name, type);
/* DECL_ARG_TYPE is only used by the back end and the back end never
sees templates. */
if (!processing_template_decl)
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)),
if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)))
fntype = build_exception_variant (fntype,
TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)));
+ if (TYPE_ATTRIBUTES (TREE_TYPE (fn)))
+ fntype = (cp_build_type_attribute_variant
+ (fntype, TYPE_ATTRIBUTES (TREE_TYPE (fn))));
TREE_TYPE (fn) = fntype;
/* Now we've got the in-charge parameter. */
FUNCTION is a FUNCTION_DECL. It was created by `grokdeclarator'.
FLAGS contains bits saying what's special about today's
- arguments. 1 == DESTRUCTOR. 2 == OPERATOR.
+ arguments. DTOR_FLAG == DESTRUCTOR.
If FUNCTION is a destructor, then we must add the `auto-delete' field
as a second parameter. There is some hair associated with the fact
if (array_expr == error_mark_node || index_exp == error_mark_node)
error ("ambiguous conversion for array subscript");
- expr = build_array_ref (array_expr, index_exp);
+ expr = build_array_ref (input_location, array_expr, index_exp);
}
if (processing_template_decl && expr != error_mark_node)
return build_min_non_dep (ARRAY_REF, expr, orig_array_expr, orig_index_exp,
either were not passed, or they are the same of DECL_TEMPLATE_PARMS. */
if (TREE_CODE (function) == TEMPLATE_DECL)
{
- gcc_assert (!template_parms
- || comp_template_parms (template_parms,
- DECL_TEMPLATE_PARMS (function)));
+ if (template_parms
+ && !comp_template_parms (template_parms,
+ DECL_TEMPLATE_PARMS (function)))
+ {
+ error ("template parameter lists provided don't match the "
+ "template parameters of %qD", function);
+ return error_mark_node;
+ }
template_parms = DECL_TEMPLATE_PARMS (function);
}
return OVL_CURRENT (fndecls);
}
- error ("prototype for %q#D does not match any in class %qT",
- function, ctype);
+ error_at (DECL_SOURCE_LOCATION (function),
+ "prototype for %q#D does not match any in class %qT",
+ function, ctype);
is_conv_op = DECL_CONV_FN_P (fndecl);
if (is_conv_op)
void
note_vague_linkage_fn (tree decl)
{
- if (!DECL_DEFERRED_FN (decl))
- {
- DECL_DEFERRED_FN (decl) = 1;
- DECL_DEFER_OUTPUT (decl) = 1;
- VEC_safe_push (tree, gc, deferred_fns, decl);
- }
+ DECL_DEFER_OUTPUT (decl) = 1;
+ VEC_safe_push (tree, gc, deferred_fns, decl);
}
/* We have just processed the DECL, which is a static data member.
VEC_safe_push (tree, gc, pending_statics, decl);
if (LOCAL_CLASS_P (current_class_type))
- permerror ("local class %q#T shall not have static data member %q#D",
+ 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;
- }
- /* Force the compiler to know when an uninitialized static const
- member is being used. */
- if (CP_TYPE_CONST_P (TREE_TYPE (decl)) && init == 0)
- TREE_USED (decl) = 1;
- 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);
}
tree value;
const char *asmspec = 0;
int flags = LOOKUP_ONLYCONVERTING;
+ tree name;
if (init
&& TREE_CODE (init) == TREE_LIST
if (TREE_CODE (value) == TYPE_DECL && init)
{
- error ("typedef %qD is initialized (use __typeof__ instead)", value);
+ error ("typedef %qD is initialized (use decltype instead)", value);
init = NULL_TREE;
}
&& DECL_CONTEXT (value) != current_class_type)
return value;
- if (DECL_NAME (value) != NULL_TREE
- && IDENTIFIER_POINTER (DECL_NAME (value))[0] == '_'
- && ! strcmp (IDENTIFIER_POINTER (DECL_NAME (value)), "_vptr"))
- error ("member %qD conflicts with virtual function table field name",
- value);
+ name = DECL_NAME (value);
+
+ if (name != NULL_TREE)
+ {
+ if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
+ {
+ error ("explicit template argument list not allowed");
+ return error_mark_node;
+ }
+
+ if (IDENTIFIER_POINTER (name)[0] == '_'
+ && ! strcmp (IDENTIFIER_POINTER (name), "_vptr"))
+ error ("member %qD conflicts with virtual function table field name",
+ value);
+ }
/* Stash away type declarations. */
if (TREE_CODE (value) == TYPE_DECL)
value = push_template_decl (value);
if (attrlist)
- cplus_decl_attributes (&value, attrlist, 0);
+ {
+ int attrflags = 0;
+
+ /* If this is a typedef that names the class for linkage purposes
+ (7.1.3p8), apply any attributes directly to the type. */
+ if (TAGGED_TYPE_P (TREE_TYPE (value))
+ && value == TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value))))
+ attrflags = ATTR_FLAG_TYPE_IN_PLACE;
+
+ cplus_decl_attributes (&value, attrlist, attrflags);
+ }
+
+ if (declspecs->specs[(int)ds_typedef]
+ && TREE_TYPE (value) != error_mark_node
+ && TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value))) != value)
+ set_underlying_type (value);
return value;
}
}
else if (init == ridpointers[(int)RID_DEFAULT])
{
- if (!defaultable_fn_p (value))
- error ("%qD cannot be defaulted", value);
- else
+ if (defaultable_fn_check (value))
{
DECL_DEFAULTED_FN (value) = 1;
DECL_INITIALIZED_IN_CLASS_P (value) = 1;
DECL_DECLARED_INLINE_P (value) = 1;
- DECL_INLINE (value) = 1;
}
}
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 (TREE_CODE (value) == VOID_TYPE)
return void_type_node;
- if (!INTEGRAL_TYPE_P (TREE_TYPE (value))
+ if (!INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (value))
&& (POINTER_TYPE_P (value)
|| !dependent_type_p (TREE_TYPE (value))))
{
error ("static member %qD cannot be a bit-field", value);
return NULL_TREE;
}
- finish_decl (value, NULL_TREE, NULL_TREE);
+ cp_finish_decl (value, NULL_TREE, false, NULL_TREE, 0);
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);
if (!late_attrs)
return;
- /* Give this type a name so we know to look it up again at instantiation
- time. */
- if (TREE_CODE (*decl_p) == TYPE_DECL
- && DECL_ORIGINAL_TYPE (*decl_p) == NULL_TREE)
- {
- tree oldt = TREE_TYPE (*decl_p);
- tree newt = build_variant_type_copy (oldt);
- DECL_ORIGINAL_TYPE (*decl_p) = oldt;
- TREE_TYPE (*decl_p) = newt;
- TYPE_NAME (newt) = *decl_p;
- TREE_USED (newt) = TREE_USED (*decl_p);
- }
-
if (DECL_P (*decl_p))
q = &DECL_ATTRIBUTES (*decl_p);
else
{
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)
{
else
return bottom;
- return cp_build_qualified_type (outer, TYPE_QUALS (type));
+ if (TYPE_ATTRIBUTES (type))
+ outer = cp_build_type_attribute_variant (outer, TYPE_ATTRIBUTES (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;
continue;
if (TREE_CODE (field) != FIELD_DECL)
{
- permerror ("%q+#D invalid; an anonymous union can only "
+ permerror (input_location, "%q+#D invalid; an anonymous union can only "
"have non-static data members", field);
continue;
}
if (TREE_PRIVATE (field))
- permerror ("private member %q+#D in anonymous union", field);
+ permerror (input_location, "private member %q+#D in anonymous union", field);
else if (TREE_PROTECTED (field))
- permerror ("protected member %q+#D in anonymous union", field);
+ permerror (input_location, "protected member %q+#D in anonymous union", field);
if (processing_template_decl)
ref = build_min_nt (COMPONENT_REF, object,
{
tree base;
- decl = build_decl (VAR_DECL, DECL_NAME (field), TREE_TYPE (field));
+ decl = build_decl (input_location,
+ VAR_DECL, DECL_NAME (field), TREE_TYPE (field));
DECL_ANON_UNION_VAR_P (decl) = 1;
+ DECL_ARTIFICIAL (decl) = 1;
base = get_base_address (object);
TREE_PUBLIC (decl) = TREE_PUBLIC (base);
{
/* Use main_decl to set the mangled name. */
DECL_NAME (anon_union_decl) = DECL_NAME (main_decl);
+ maybe_commonize_var (anon_union_decl);
mangle_decl (anon_union_decl);
DECL_NAME (anon_union_decl) = NULL_TREE;
}
e = 2;
if (e == 2)
- permerror ("%<operator new%> takes type %<size_t%> (%qT) "
+ permerror (input_location, "%<operator new%> takes type %<size_t%> (%qT) "
"as first parameter", size_type_node);
switch (e)
comdat_linkage (tree decl)
{
if (flag_weak)
- make_decl_one_only (decl);
+ make_decl_one_only (decl, cxx_comdat_group (decl));
else if (TREE_CODE (decl) == FUNCTION_DECL
|| (TREE_CODE (decl) == VAR_DECL && DECL_ARTIFICIAL (decl)))
/* We can just emit function and compiler-generated variables
}
}
- if (DECL_LANG_SPECIFIC (decl))
- DECL_COMDAT (decl) = 1;
+ DECL_COMDAT (decl) = 1;
}
/* For win32 we also want to put explicit instantiations in
|| (! DECL_EXPLICIT_INSTANTIATION (decl)
&& ! DECL_TEMPLATE_SPECIALIZATION (decl)))
{
- make_decl_one_only (decl);
+ make_decl_one_only (decl, cxx_comdat_group (decl));
if (TREE_CODE (decl) == VAR_DECL)
{
}
}
+/* 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_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 (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,
using various heuristics. */
|| (DECL_ASSEMBLER_NAME_SET_P (decl)
&& TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
return true;
+ /* Functions marked "dllexport" must be emitted so that they are
+ visible to other DLLs. */
+ if (lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)))
+ return true;
/* Otherwise, DECL does not need to be emitted -- yet. A subsequent
reference to DECL might cause it to be emitted later. */
return false;
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);
if (TREE_TYPE (DECL_INITIAL (vtbl)) == 0)
{
- tree expr = store_init_value (vtbl, DECL_INITIAL (vtbl));
+ tree expr = store_init_value (vtbl, DECL_INITIAL (vtbl), LOOKUP_NORMAL);
/* It had better be all done at compile-time. */
gcc_assert (!expr);
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 (!DECL_EXTERN_C_P (decl))
{
TREE_PUBLIC (decl) = 0;
- DECL_ONE_ONLY (decl) = 0;
+ DECL_WEAK (decl) = 0;
+ DECL_COMMON (decl) = 0;
+ DECL_COMDAT_GROUP (decl) = NULL_TREE;
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;
+ DECL_VISIBILITY (decl) = (enum symbol_visibility) visibility;
return true;
}
return false;
{
tree class_type = NULL_TREE;
bool use_template;
+ bool orig_visibility_specified;
+ enum symbol_visibility orig_visibility;
/* Remember that all decls get VISIBILITY_DEFAULT when built. */
maybe_clone_body. */
gcc_assert (!DECL_CLONED_FUNCTION_P (decl));
+ orig_visibility_specified = DECL_VISIBILITY_SPECIFIED (decl);
+ orig_visibility = DECL_VISIBILITY (decl);
+
if (TREE_CODE (decl) == TYPE_DECL)
{
if (CLASS_TYPE_P (TREE_TYPE (decl)))
|| ! DECL_VISIBILITY_SPECIFIED (decl))
constrain_visibility (decl, tvis);
}
+ 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
+ variable or function with linkage, unless
+ o the variable or function has extern "C" linkage (7.5 [dcl.link]), or
+ o the variable or function is not used (3.2 [basic.def.odr]) or is
+ defined in the same translation unit.
+
+ 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);
+
+ /* If visibility changed and DECL already has DECL_RTL, ensure
+ symbol flags are updated. */
+ if ((DECL_VISIBILITY (decl) != orig_visibility
+ || DECL_VISIBILITY_SPECIFIED (decl) != orig_visibility_specified)
+ && ((TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
+ || TREE_CODE (decl) == FUNCTION_DECL)
+ && DECL_RTL_SET_P (decl))
+ make_decl_rtl (decl);
}
/* By default, static data members and function members receive
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));
/* We use a type that is big enough to contain a mutex as well
as an integer counter. */
guard_type = targetm.cxx.guard_type ();
- guard = build_decl (VAR_DECL, sname, guard_type);
+ guard = build_decl (DECL_SOURCE_LOCATION (decl),
+ VAR_DECL, sname, guard_type);
/* The guard should have the same linkage as what it guards. */
TREE_PUBLIC (guard) = TREE_PUBLIC (decl);
TREE_STATIC (guard) = TREE_STATIC (decl);
DECL_COMMON (guard) = DECL_COMMON (decl);
- DECL_ONE_ONLY (guard) = DECL_ONE_ONLY (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);
guard_value = integer_one_node;
if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard)))
guard_value = convert (TREE_TYPE (guard), guard_value);
- guard = cp_build_binary_op (BIT_AND_EXPR, guard, guard_value,
+ guard = cp_build_binary_op (input_location,
+ BIT_AND_EXPR, guard, guard_value,
tf_warning_or_error);
}
guard_value = integer_zero_node;
if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard)))
guard_value = convert (TREE_TYPE (guard), guard_value);
- return cp_build_binary_op (EQ_EXPR, guard, guard_value,
+ return cp_build_binary_op (input_location,
+ EQ_EXPR, guard, guard_value,
tf_warning_or_error);
}
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;
DECL_GLOBAL_CTOR_P (current_function_decl) = 1;
else
DECL_GLOBAL_DTOR_P (current_function_decl) = 1;
- DECL_LANG_SPECIFIC (current_function_decl)->decl_flags.u2sel = 1;
body = begin_compound_stmt (BCS_FN_BODY);
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,
type);
TREE_PUBLIC (ssdf_decl) = 0;
DECL_ARTIFICIAL (ssdf_decl) = 1;
- DECL_INLINE (ssdf_decl) = 1;
/* Put this function in the list of functions to be called from the
static constructors and destructors. */
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. */
|| DECL_ONE_ONLY (decl) \
|| DECL_WEAK (decl)))
+/* Called from one_static_initialization_or_destruction(),
+ via walk_tree.
+ Walks the initializer list of a global variable and looks for
+ temporary variables (DECL_NAME() == NULL and DECL_ARTIFICIAL != 0)
+ and that have their DECL_CONTEXT() == NULL.
+ For each such temporary variable, set their DECL_CONTEXT() to
+ the current function. This is necessary because otherwise
+ some optimizers (enabled by -O2 -fprofile-arcs) might crash
+ when trying to refer to a temporary variable that does not have
+ it's DECL_CONTECT() properly set. */
+static tree
+fix_temporary_vars_context_r (tree *node,
+ int *unused ATTRIBUTE_UNUSED,
+ void *unused1 ATTRIBUTE_UNUSED)
+{
+ gcc_assert (current_function_decl);
+
+ if (TREE_CODE (*node) == BIND_EXPR)
+ {
+ tree var;
+
+ for (var = BIND_EXPR_VARS (*node); var; var = DECL_CHAIN (var))
+ if (TREE_CODE (var) == VAR_DECL
+ && !DECL_NAME (var)
+ && DECL_ARTIFICIAL (var)
+ && !DECL_CONTEXT (var))
+ DECL_CONTEXT (var) = current_function_decl;
+ }
+
+ return NULL_TREE;
+}
+
/* Set up to handle the initialization or destruction of DECL. If
INITP is nonzero, we are initializing the variable. Otherwise, we
are destroying it. */
information. */
input_location = DECL_SOURCE_LOCATION (decl);
+ /* Make sure temporary variables in the initialiser all have
+ their DECL_CONTEXT() set to a value different from NULL_TREE.
+ This can happen when global variables initialisers are built.
+ In that case, the DECL_CONTEXT() of the global variables _AND_ of all
+ the temporary variables that might have been generated in the
+ accompagning initialisers is NULL_TREE, meaning the variables have been
+ declared in the global namespace.
+ What we want to do here is to fix that and make sure the DECL_CONTEXT()
+ of the temporaries are set to the current function decl. */
+ cp_walk_tree_without_duplicates (&init,
+ fix_temporary_vars_context_r,
+ NULL);
+
/* Because of:
[class.access.spec]
last to destroy the variable. */
else if (initp)
guard_cond
- = cp_build_binary_op (EQ_EXPR,
+ = cp_build_binary_op (input_location,
+ EQ_EXPR,
cp_build_unary_op (PREINCREMENT_EXPR,
- guard,
- /*noconvert=*/1,
- tf_warning_or_error),
+ guard,
+ /*noconvert=*/1,
+ tf_warning_or_error),
integer_one_node,
tf_warning_or_error);
else
guard_cond
- = cp_build_binary_op (EQ_EXPR,
+ = cp_build_binary_op (input_location,
+ EQ_EXPR,
cp_build_unary_op (PREDECREMENT_EXPR,
- guard,
- /*noconvert=*/1,
- tf_warning_or_error),
+ guard,
+ /*noconvert=*/1,
+ tf_warning_or_error),
integer_zero_node,
tf_warning_or_error);
/* Build the outer if-stmt to check for initialization or destruction. */
init_if_stmt = begin_if_stmt ();
cond = initp ? integer_one_node : integer_zero_node;
- cond = cp_build_binary_op (EQ_EXPR,
+ cond = cp_build_binary_op (input_location,
+ EQ_EXPR,
initialize_p_decl,
cond,
tf_warning_or_error);
/* Conditionalize this initialization on being in the right priority
and being initializing/finalizing appropriately. */
priority_if_stmt = begin_if_stmt ();
- cond = cp_build_binary_op (EQ_EXPR,
+ cond = cp_build_binary_op (input_location,
+ EQ_EXPR,
priority_decl,
build_int_cst (NULL_TREE, priority),
tf_warning_or_error);
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);
}
}
{
case PTRMEM_CST:
if (TYPE_PTRMEMFUNC_P (TREE_TYPE (t)))
- cgraph_mark_needed_node (cgraph_node (PTRMEM_CST_MEMBER (t)));
+ cgraph_mark_address_taken_node (cgraph_node (PTRMEM_CST_MEMBER (t)));
break;
case BASELINK:
if (TREE_CODE (BASELINK_FUNCTIONS (t)) == FUNCTION_DECL)
- cgraph_mark_needed_node (cgraph_node (BASELINK_FUNCTIONS (t)));
+ 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)
- && 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));
/* 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, emit one for each java function that we've emitted. */
+ supported, collect and return all the functions for which we should
+ emit a hidden alias. */
-static void
-build_java_method_aliases (void)
+static struct pointer_set_t *
+collect_candidates_for_java_method_aliases (void)
{
struct cgraph_node *node;
+ struct pointer_set_t *candidates = NULL;
#ifndef HAVE_GAS_HIDDEN
- return;
+ return candidates;
#endif
for (node = cgraph_nodes; node ; node = node->next)
{
tree fndecl = node->decl;
- if (TREE_ASM_WRITTEN (fndecl)
- && DECL_CONTEXT (fndecl)
+ if (DECL_CONTEXT (fndecl)
&& TYPE_P (DECL_CONTEXT (fndecl))
&& TYPE_FOR_JAVA (DECL_CONTEXT (fndecl))
&& TARGET_USE_LOCAL_THUNK_ALIAS_P (fndecl))
{
+ if (candidates == NULL)
+ candidates = pointer_set_create ();
+ pointer_set_insert (candidates, fndecl);
+ }
+ }
+
+ return candidates;
+}
+
+
+/* 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, emit one for each java function that we've emitted.
+ CANDIDATES is the set of FUNCTION_DECLs that were gathered
+ by collect_candidates_for_java_method_aliases. */
+
+static void
+build_java_method_aliases (struct pointer_set_t *candidates)
+{
+ struct cgraph_node *node;
+
+#ifndef HAVE_GAS_HIDDEN
+ return;
+#endif
+
+ for (node = cgraph_nodes; node ; node = node->next)
+ {
+ tree fndecl = node->decl;
+
+ if (TREE_ASM_WRITTEN (fndecl)
+ && pointer_set_contains (candidates, fndecl))
+ {
/* Mangle the name in a predictable way; we need to reference
this from a java compiled object file. */
tree oid, nid, alias;
}
}
+/* 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. */
+
+static bool
+decl_defined_p (tree decl)
+{
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ return (DECL_INITIAL (decl) != NULL_TREE);
+ else
+ {
+ gcc_assert (TREE_CODE (decl) == VAR_DECL);
+ return !DECL_EXTERNAL (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
+no_linkage_error (tree decl)
+{
+ tree t = no_linkage_check (TREE_TYPE (decl), /*relaxed_p=*/false);
+ if (TYPE_ANONYMOUS_P (t))
+ {
+ permerror (0, "%q+#D, declared using anonymous type, "
+ "is used but never defined", decl);
+ if (is_typedef_decl (TYPE_NAME (t)))
+ permerror (0, "%q+#D does not refer to the unqualified type, "
+ "so it is not used for linkage", TYPE_NAME (t));
+ }
+ else
+ permerror (0, "%q+#D, declared using local type %qT, "
+ "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
unsigned ssdf_count = 0;
int retries = 0;
tree decl;
+ struct pointer_set_t *candidates;
locus = input_location;
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_ARTIFICIAL (decl) && ! DECL_INITIAL (decl)
+ if (DECL_DEFAULTED_FN (decl) && ! DECL_INITIAL (decl)
&& (! DECL_REALLY_EXTERN (decl) || possibly_inlined_p (decl)))
{
/* Even though we're already at the top-level, we push
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. */
- TREE_USED (decl) && DECL_DECLARED_INLINE_P (decl)
+ DECL_ODR_USED (decl) && DECL_DECLARED_INLINE_P (decl)
/* If the definition actually was available here, then the
fact that the function was not defined merely represents
that for some reason (use of a template repository,
}
}
+ /* So must decls that use a type with no linkage. */
+ 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);
linkage now. */
pop_lang_context ();
+ /* Collect candidates for Java hidden aliases. */
+ candidates = collect_candidates_for_java_method_aliases ();
+
cgraph_finalize_compilation_unit ();
- cgraph_optimize ();
/* Now, issue warnings about static, but not defined, functions,
etc., and emit debugging information. */
VEC_length (tree, pending_statics));
}
+ perform_deferred_noexcept_checks ();
+
/* Generate hidden aliases for Java. */
- build_java_method_aliases ();
+ if (candidates)
+ {
+ build_java_method_aliases (candidates);
+ pointer_set_destroy (candidates);
+ }
finish_repo ();
/* FN is an OFFSET_REF, DOTSTAR_EXPR or MEMBER_REF indicating the
function to call in parse-tree form; it has not yet been
semantically analyzed. ARGS are the arguments to the function.
- They have already been semantically analyzed. */
+ They have already been semantically analyzed. This may change
+ ARGS. */
tree
-build_offset_ref_call_from_tree (tree fn, tree args)
+build_offset_ref_call_from_tree (tree fn, VEC(tree,gc) **args)
{
tree orig_fn;
- tree orig_args;
+ VEC(tree,gc) *orig_args = NULL;
tree expr;
tree object;
orig_fn = fn;
- orig_args = args;
object = TREE_OPERAND (fn, 0);
if (processing_template_decl)
gcc_assert (TREE_CODE (fn) == DOTSTAR_EXPR
|| TREE_CODE (fn) == MEMBER_REF);
if (type_dependent_expression_p (fn)
- || any_type_dependent_arguments_p (args))
- return build_nt_call_list (fn, args);
+ || any_type_dependent_arguments_p (*args))
+ return build_nt_call_vec (fn, *args);
+
+ orig_args = make_tree_vector_copy (*args);
/* Transform the arguments and add the implicit "this"
parameter. That must be done before the FN is transformed
because we depend on the form of FN. */
- args = build_non_dependent_args (args);
+ 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);
- args = tree_cons (NULL_TREE, object, args);
+ 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);
- args = tree_cons (NULL_TREE, object_addr, args);
+ VEC_safe_insert (tree, gc, *args, 0, object_addr);
}
- expr = cp_build_function_call (fn, args, tf_warning_or_error);
+ expr = cp_build_function_call_vec (fn, args, tf_warning_or_error);
if (processing_template_decl && expr != error_mark_node)
- return build_min_non_dep_call_list (expr, orig_fn, orig_args);
+ expr = build_min_non_dep_call_vec (expr, orig_fn, orig_args);
+
+ if (orig_args != NULL)
+ release_tree_vector (orig_args);
+
return expr;
}
gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
if (DECL_UNINLINABLE (decl))
return false;
- if (!optimize)
+ if (!optimize || pragma_java_exceptions)
return DECL_DECLARED_INLINE_P (decl);
/* When optimizing, we might inline everything when flatten
attribute or heuristics inlining for size or autoinlining
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
decl = OVL_CURRENT (decl);
}
+ /* Set TREE_USED for the benefit of -Wunused. */
TREE_USED (decl) = 1;
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
- 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;
+
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_DELETED_FN (decl))
+ {
+ 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 (processing_template_decl)
+ /* 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
+ might need special handling for. */
+ if ((TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL)
+ || DECL_LANG_SPECIFIC (decl) == NULL
+ || DECL_THUNK_P (decl))
return;
- if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl)
- && !TREE_ASM_WRITTEN (decl))
- /* Remember it, so we can check it was defined. */
+ /* 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;
+
+ /* If within finish_function, defer the rest until that function
+ finishes, otherwise it might recurse. */
+ if (defer_mark_used_calls)
{
- if (DECL_DEFERRED_FN (decl))
- return;
+ VEC_safe_push (tree, gc, deferred_mark_used_calls, decl);
+ return;
+ }
- /* 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. */
- if (DECL_ARTIFICIAL (decl) && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)
- && !DECL_THUNK_P (decl))
- DECL_SOURCE_LOCATION (decl) = input_location;
+ /* 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;
- note_vague_linkage_fn (decl);
+ DECL_ODR_USED (decl) = 1;
+ if (DECL_CLONED_FUNCTION_P (decl))
+ DECL_ODR_USED (DECL_CLONED_FUNCTION (decl)) = 1;
+
+ /* DR 757: A type without linkage shall not be used as the type of a
+ variable or function with linkage, unless
+ o the variable or function has extern "C" linkage (7.5 [dcl.link]), or
+ o the variable or function is not used (3.2 [basic.def.odr]) or is
+ defined in the same translation unit. */
+ if (cxx_dialect > cxx98
+ && decl_linkage (decl) != lk_none
+ && !DECL_EXTERN_C_P (decl)
+ && !DECL_ARTIFICIAL (decl)
+ && !decl_defined_p (decl)
+ && no_linkage_check (TREE_TYPE (decl), /*relaxed_p=*/false))
+ {
+ if (is_local_extern (decl))
+ /* There's no way to define a local extern, and adding it to
+ the vector interferes with GC, so give an error now. */
+ no_linkage_error (decl);
+ else
+ VEC_safe_push (tree, gc, no_linkage_decls, decl);
}
- assemble_external (decl);
+ if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl)
+ && !DECL_INITIAL (decl) && !DECL_ARTIFICIAL (decl))
+ /* Remember it, so we can check it was defined. */
+ note_vague_linkage_fn (decl);
/* Is it a synthesized method that needs to be synthesized? */
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)
&& DECL_DEFAULTED_FN (decl)
- && !DECL_THUNK_P (decl)
- && ! DECL_INITIAL (decl)
- /* Kludge: don't synthesize for default args. Unfortunately this
- rules out initializers of namespace-scoped objects too, but
- it's sort-of ok if the implicit ctor or dtor decl keeps
- pointing to the class location. */
- && current_function_decl)
+ && ! DECL_INITIAL (decl))
{
+ /* 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. */
+ DECL_SOURCE_LOCATION (decl) = input_location;
+
+ /* Synthesizing an implicitly defined member 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
+ 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
+ it at the use site produces better error messages. */
+ ++function_depth;
synthesize_method (decl);
- /* If we've already synthesized the method we don't need to
+ --function_depth;
+ /* If this is a synthesized method we don't need to
do the instantiation test below. */
}
- else if (TREE_CODE (decl) == FUNCTION_DECL
- && DECL_DELETED_FN (decl))
- {
- error ("deleted function %q+D", decl);
- error ("used here");
- }
- else if ((DECL_NON_THUNK_FUNCTION_P (decl) || TREE_CODE (decl) == VAR_DECL)
- && DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)
+ else if ((TREE_CODE (decl) == FUNCTION_DECL || TREE_CODE (decl) == VAR_DECL)
+ && DECL_TEMPLATE_INFO (decl)
&& (!DECL_EXPLICIT_INSTANTIATION (decl)
- || (TREE_CODE (decl) == FUNCTION_DECL
- && possibly_inlined_p
- (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))))
+ || always_instantiate_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
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"