#include "tree-dump.h"
#include "intl.h"
#include "gimple.h"
+#include "pointer-set.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;
}
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)
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, input_location);
+ 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,
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.
}
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;
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)
cplus_decl_attributes (&value, attrlist, attrflags);
}
- if (declspecs->specs[(int)ds_typedef])
+ 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;
error ("static member %qD cannot be a bit-field", value);
return NULL_TREE;
}
- finish_decl (value, NULL_TREE, NULL_TREE, NULL_TREE);
+ cp_finish_decl (value, NULL_TREE, false, NULL_TREE, 0);
if (width != error_mark_node)
{
else
return bottom;
+ if (TYPE_ATTRIBUTES (type))
+ outer = cp_build_type_attribute_variant (outer, TYPE_ATTRIBUTES (type));
return cp_build_qualified_type (outer, TYPE_QUALS (type));
}
{
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);
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, 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)
+{
+ /* 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)));
+}
+
/* Determine whether or not we want to specifically import or export CTYPE,
using various heuristics. */
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;
|| ! 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. */
/* 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);
+ DECL_COMDAT_GROUP (guard) = DECL_COMDAT_GROUP (decl);
if (TREE_PUBLIC (decl))
DECL_WEAK (guard) = DECL_WEAK (decl);
DECL_VISIBILITY (guard) = DECL_VISIBILITY (decl);
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);
mark_decl_referenced (vtbl);
}
else 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. */
/* 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;
}
}
+/* 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);
+ }
+}
+
+/* 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);
+}
+
/* 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;
reconsider = true;
}
- if (!gimple_body (decl))
+ if (!DECL_SAVED_TREE (decl))
continue;
/* We lie to the back end, pretending that some functions
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;
+
+ 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're going to need to write this function out, and
there's already a body for it, create RTL for it now.
for (i = 0; VEC_iterate (tree, deferred_fns, i, decl); ++i)
{
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 (i = 0; VEC_iterate (tree, no_linkage_decls, i, decl); ++i)
+ if (!decl_defined_p (decl))
+ no_linkage_error (decl);
+
/* 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. */
}
/* Generate hidden aliases for Java. */
- build_java_method_aliases ();
+ if (candidates)
+ {
+ build_java_method_aliases (candidates);
+ pointer_set_destroy (candidates);
+ }
finish_repo ();
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 (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_DELETED_FN (decl))
{
return;
}
/* If we don't need a value, then we don't need to synthesize DECL. */
- if (skip_evaluation)
+ 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
+ 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;
+
+ /* 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
if (processing_template_decl)
return;
+ 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);
+ }
+
if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl)
- && !TREE_ASM_WRITTEN (decl))
+ && !DECL_INITIAL (decl) && !DECL_ARTIFICIAL (decl))
/* Remember it, so we can check it was defined. */
- {
- if (DECL_DEFERRED_FN (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;
-
- note_vague_linkage_fn (decl);
- }
+ 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 ((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
processing_template_decl = saved_processing_template_decl;
}
-/* Given function PARM_DECL PARM, return its index in the function's list
- of parameters, beginning with 1. */
-
-int
-parm_index (tree parm)
-{
- int index;
- tree arg;
-
- for (index = 1, arg = DECL_ARGUMENTS (DECL_CONTEXT (parm));
- arg;
- ++index, arg = TREE_CHAIN (arg))
- {
- if (DECL_NAME (parm) == DECL_NAME (arg))
- break;
- if (DECL_ARTIFICIAL (arg))
- --index;
- }
-
- gcc_assert (arg);
- return index;
-}
-
#include "gt-cp-decl2.h"