/* Process declarations and variables for C++ compiler.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
if (!DECL_LANG_SPECIFIC (decl))
retrofit_lang_decl (decl);
DECL_LANG_SPECIFIC (decl)->u.base.u2sel = 1;
- if (DECL_LANG_SPECIFIC (t))
+ if (DECL_DISCRIMINATOR_SET_P (t))
DECL_DISCRIMINATOR (decl) = DECL_DISCRIMINATOR (t) + 1;
else
DECL_DISCRIMINATOR (decl) = 1;
interested in their types. */
return 0;
+ gcc_assert (DECL_P (newdecl));
+
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
tree f1 = TREE_TYPE (newdecl);
/* Don't warn about extern decl followed by definition. */
&& !(DECL_EXTERNAL (olddecl) && ! DECL_EXTERNAL (newdecl))
/* Don't warn about friends, let add_friend take care of it. */
- && ! (newdecl_is_friend || DECL_FRIEND_P (olddecl)))
+ && ! (newdecl_is_friend || DECL_FRIEND_P (olddecl))
+ /* Don't warn about declaration followed by specialization. */
+ && (! DECL_TEMPLATE_SPECIALIZATION (newdecl)
+ || DECL_TEMPLATE_SPECIALIZATION (olddecl)))
{
warning (OPT_Wredundant_decls, "redundant redeclaration of %qD in same scope", newdecl);
warning (OPT_Wredundant_decls, "previous declaration of %q+D", olddecl);
/* Merge the data types specified in the two decls. */
newtype = merge_types (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
- /* If merge_types produces a non-typedef type, just use the old type. */
- if (TREE_CODE (newdecl) == TYPE_DECL
- && newtype == DECL_ORIGINAL_TYPE (newdecl))
+ /* For typedefs use the old type, as the new type's DECL_NAME points
+ at newdecl, which will be ggc_freed. */
+ if (TREE_CODE (newdecl) == TYPE_DECL)
newtype = oldtype;
if (TREE_CODE (newdecl) == VAR_DECL)
SET_DECL_INIT_PRIORITY (olddecl, DECL_INIT_PRIORITY (newdecl));
DECL_HAS_INIT_PRIORITY_P (olddecl) = 1;
}
- /* Likewise for DECL_USER_ALIGN and DECL_PACKED. */
+ /* Likewise for DECL_ALIGN, DECL_USER_ALIGN and DECL_PACKED. */
+ if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl))
+ {
+ DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
+ DECL_USER_ALIGN (newdecl) |= DECL_USER_ALIGN (olddecl);
+ }
DECL_USER_ALIGN (olddecl) = DECL_USER_ALIGN (newdecl);
if (TREE_CODE (newdecl) == FIELD_DECL)
DECL_PACKED (olddecl) = DECL_PACKED (newdecl);
define_label (location_t location, tree name)
{
tree ret;
- timevar_start (TV_NAME_LOOKUP);
+ bool running = timevar_cond_start (TV_NAME_LOOKUP);
ret = define_label_1 (location, name);
- timevar_stop (TV_NAME_LOOKUP);
+ timevar_cond_stop (TV_NAME_LOOKUP, running);
return ret;
}
error ("%<constexpr%> cannot be used for type declarations");
}
+ if (declspecs->attributes && declared_type)
+ {
+ location_t loc = input_location;
+ if (!CLASS_TYPE_P (declared_type)
+ || !CLASSTYPE_TEMPLATE_INSTANTIATION (declared_type))
+ /* For a non-template class, use the name location; for a template
+ class (an explicit instantiation), use the current location. */
+ input_location = location_of (declared_type);
+ warning (0, "attribute ignored in declaration of %q#T", declared_type);
+ warning (0, "attribute for %q#T must follow the %qs keyword",
+ declared_type, class_key_or_enum_as_string (declared_type));
+ input_location = loc;
+ }
+
return declared_type;
}
if (!t)
return NULL_TREE;
- if (declspecs->attributes)
- {
- warning (0, "attribute ignored in declaration of %q+#T", t);
- warning (0, "attribute for %q+#T must follow the %qs keyword",
- t, class_key_or_enum_as_string (t));
-
- }
-
if (maybe_process_partial_specialization (t) == error_mark_node)
return NULL_TREE;
}
/* If #pragma weak was used, mark the decl weak now. */
- maybe_apply_pragma_weak (decl);
+ if (!processing_template_decl)
+ maybe_apply_pragma_weak (decl);
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_DECLARED_INLINE_P (decl)
}
else if (!COMPLETE_TYPE_P (type))
{
- error ("%qD has incomplete type", decl);
+ error ("%q#D has incomplete type", decl);
TREE_TYPE (decl) = error_mark_node;
return NULL_TREE;
}
if ((type_build_ctor_call (type) || CLASS_TYPE_P (type))
&& !(flags & LOOKUP_ALREADY_DIGESTED)
&& !(init && BRACE_ENCLOSED_INITIALIZER_P (init)
- && CP_AGGREGATE_TYPE_P (type)))
+ && CP_AGGREGATE_TYPE_P (type)
+ && (CLASS_TYPE_P (type)
+ || type_has_extended_temps (type))))
{
init_code = build_aggr_init_full_exprs (decl, init, flags);
}
else if (was_readonly)
TREE_READONLY (decl) = 1;
+
+ /* Likewise if it needs destruction. */
+ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+ TREE_READONLY (decl) = 0;
}
make_rtl_for_nonlocal_decl (decl, init, asmspec);
return 0;
else if (cxx_dialect >= cxx0x && !INTEGRAL_OR_ENUMERATION_TYPE_P (type))
{
- if (literal_type_p (type))
+ if (!COMPLETE_TYPE_P (type))
+ error ("in-class initialization of static data member %q#D of "
+ "incomplete type", decl);
+ else if (literal_type_p (type))
permerror (input_location,
"%<constexpr%> needed for in-class initialization of "
"static data member %q#D of non-integral type", decl);
return type;
}
+/* Functions for adjusting the visibility of a tagged type and its nested
+ types when it gets a name for linkage purposes from a typedef. */
+
+static void bt_reset_linkage (binding_entry, void *);
+static void
+reset_type_linkage (tree type)
+{
+ set_linkage_according_to_type (type, TYPE_MAIN_DECL (type));
+ if (CLASS_TYPE_P (type))
+ binding_table_foreach (CLASSTYPE_NESTED_UTDS (type), bt_reset_linkage, NULL);
+}
+static void
+bt_reset_linkage (binding_entry b, void *data ATTRIBUTE_UNUSED)
+{
+ reset_type_linkage (b->type);
+}
+
/* Given declspecs and a declarator (abstract or otherwise), determine
the name and type of the object declared and construct a DECL node
for it.
the object as `const'. */
if (constexpr_p && innermost_code != cdk_function)
{
- if (type_quals & TYPE_QUAL_CONST)
- error ("both %<const%> and %<constexpr%> cannot be used here");
if (type_quals & TYPE_QUAL_VOLATILE)
error ("both %<volatile%> and %<constexpr%> cannot be used here");
if (TREE_CODE (type) != REFERENCE_TYPE)
= TYPE_IDENTIFIER (type);
/* Adjust linkage now that we aren't anonymous anymore. */
- set_linkage_according_to_type (type, TYPE_MAIN_DECL (type));
- determine_visibility (TYPE_MAIN_DECL (type));
+ reset_type_linkage (type);
/* FIXME remangle member functions; member functions of a
type with external linkage have external linkage. */
local_variable_p_walkfn (tree *tp, int *walk_subtrees,
void *data ATTRIBUTE_UNUSED)
{
- if (local_variable_p (*tp) && !DECL_ARTIFICIAL (*tp))
+ if (local_variable_p (*tp)
+ && (!DECL_ARTIFICIAL (*tp) || DECL_NAME (*tp) == this_identifier))
return *tp;
else if (TYPE_P (*tp))
*walk_subtrees = 0;
return NULL_TREE;
}
-
/* Check that ARG, which is a default-argument expression for a
parameter DECL, is valid. Returns ARG, or ERROR_MARK_NODE, if
something goes wrong. DECL may also be a _TYPE node, rather than a
return error_mark_node;
}
+ if (warn_zero_as_null_pointer_constant
+ && c_inhibit_evaluation_warnings == 0
+ && (TYPE_PTR_P (decl_type) || TYPE_PTR_TO_MEMBER_P (decl_type))
+ && null_ptr_cst_p (arg)
+ && !NULLPTR_TYPE_P (TREE_TYPE (arg)))
+ {
+ warning (OPT_Wzero_as_null_pointer_constant,
+ "zero as null pointer constant");
+ return nullptr_node;
+ }
+
/* [dcl.fct.default]
Local variables shall not be used in default argument
var = cp_walk_tree_without_duplicates (&arg, local_variable_p_walkfn, NULL);
if (var)
{
- error ("default argument %qE uses local variable %qD", arg, var);
+ if (DECL_NAME (var) == this_identifier)
+ permerror (input_location, "default argument %qE uses %qD", arg, var);
+ else
+ error ("default argument %qE uses local variable %qD", arg, var);
return error_mark_node;
}
bool
move_fn_p (const_tree d)
{
- tree args;
- tree arg_type;
- bool result = false;
-
gcc_assert (DECL_FUNCTION_MEMBER_P (d));
if (cxx_dialect == cxx98)
if (TREE_CODE (d) == TEMPLATE_DECL
|| (DECL_TEMPLATE_INFO (d)
&& DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (d))))
- /* Instantiations of template member functions are never copy
+ /* Instantiations of template member functions are never move
functions. Note that member functions of templated classes are
represented as template functions internally, and we must
- accept those as copy functions. */
+ accept those as move functions. */
return 0;
+ return move_signature_fn_p (d);
+}
+
+/* D is a constructor or overloaded `operator='.
+
+ Then, this function returns true when D has the same signature as a move
+ constructor or move assignment operator (because either it is such a
+ ctor/op= or it is a template specialization with the same signature),
+ false otherwise. */
+
+bool
+move_signature_fn_p (const_tree d)
+{
+ tree args;
+ tree arg_type;
+ bool result = false;
+
args = FUNCTION_FIRST_USER_PARMTYPE (d);
if (!args)
return 0;
{
tree type;
- if (decl == error_mark_node)
- return error_mark_node;
-
/* In the case of:
struct S { struct S *p; };
TYPE_FOR_JAVA (ref) = 1;
base_binfo = NULL_TREE;
- if (CLASS_TYPE_P (basetype) && !dependent_type_p (basetype))
+ if (CLASS_TYPE_P (basetype) && !dependent_scope_p (basetype))
{
base_binfo = TYPE_BINFO (basetype);
/* The original basetype could have been a typedef'd type. */
BINFO_BASE_ACCESS_APPEND (binfo, access);
}
- if (VEC_space (tree, CLASSTYPE_VBASECLASSES (ref), 1))
- /* If we have space in the vbase vector, we must have shared at
+ if (VEC_length (tree, CLASSTYPE_VBASECLASSES (ref)) < max_vbases)
+ /* If we didn't get max_vbases vbases, we must have shared at
least one of them, and are therefore diamond shaped. */
CLASSTYPE_DIAMOND_SHAPED_P (ref) = 1;
/* Do not push the decl more than once, unless we need to
compare underlying types at instantiation time */
if (!enumtype
+ || TREE_CODE (enumtype) != ENUMERAL_TYPE
|| (underlying_type
&& dependent_type_p (underlying_type))
|| (ENUM_UNDERLYING_TYPE (enumtype)
for (t = TYPE_MAIN_VARIANT (enumtype); t; t = TYPE_NEXT_VARIANT (t))
TYPE_VALUES (t) = TYPE_VALUES (enumtype);
+ if (at_class_scope_p ()
+ && COMPLETE_TYPE_P (current_class_type)
+ && UNSCOPED_ENUM_P (enumtype))
+ insert_late_enum_def_into_classtype_sorted_fields (enumtype,
+ current_class_type);
+
/* Finish debugging output for this type. */
rest_of_type_compilation (enumtype, namespace_bindings_p ());
}
{
value = cxx_constant_value (value);
- if (TREE_CODE (value) == INTEGER_CST
- && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (value)))
- {
- value = perform_integral_promotions (value);
- }
- else
+ if (TREE_CODE (value) != INTEGER_CST
+ || ! INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (value)))
{
- error ("enumerator value for %qD is not an integer constant", name);
+ error ("enumerator value for %qD is not an integer constant",
+ name);
value = NULL_TREE;
}
}
if (DECL_NOT_REALLY_EXTERN (decl1))
DECL_EXTERNAL (decl1) = 0;
- if (ctx != NULL_TREE && DECL_DECLARED_INLINE_P (ctx)
- && TREE_PUBLIC (ctx))
+ if (ctx != NULL_TREE && vague_linkage_p (ctx))
/* This is a function in a local class in an extern inline
- function. */
+ or template function. */
comdat_linkage (decl1);
}
/* If this function belongs to an interface, it is public.
cleanup = call;
}
+ /* build_delete sets the location of the destructor call to the
+ current location, even though the destructor is going to be
+ called later, at the end of the current scope. This can lead to
+ a "jumpy" behaviour for users of debuggers when they step around
+ the end of the block. So let's unset the location of the
+ destructor call instead. */
+ if (cleanup != NULL && EXPR_P (cleanup))
+ SET_EXPR_LOCATION (cleanup, UNKNOWN_LOCATION);
return cleanup;
}
+
\f
/* When a stmt has been parsed, this function is called. */