/* 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
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
#include "expr.h"
#include "flags.h"
#include "cp-tree.h"
+#include "tree-iterator.h"
#include "tree-inline.h"
#include "decl.h"
#include "intl.h"
static void store_parm_decls (tree);
static void initialize_local_var (tree, tree);
static void expand_static_init (tree, tree);
-static tree next_initializable_field (tree);
/* The following symbols are subsumed in the cp_global_trees array, and
listed here individually for documentation purposes.
return 1;
}
+/* Saved errorcount to avoid -Wunused-but-set-{parameter,variable} warnings
+ when errors were reported, except for -Werror-unused-but-set-*. */
+static int unused_but_set_errorcount;
+
/* Exit a binding level.
Pop the level off, and restore the state of the identifier-decl mappings
that were in effect when this level was entered.
= current_binding_level->kind == sk_for && flag_new_for_scope == 1;
/* Before we remove the declarations first check for unused variables. */
- if (warn_unused_variable
+ if ((warn_unused_variable || warn_unused_but_set_variable)
&& !processing_template_decl)
for (decl = getdecls (); decl; decl = TREE_CHAIN (decl))
if (TREE_CODE (decl) == VAR_DECL
- && ! TREE_USED (decl)
+ && (! TREE_USED (decl) || !DECL_READ_P (decl))
&& ! DECL_IN_SYSTEM_HEADER (decl)
&& DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl))
- warning (OPT_Wunused_variable, "unused variable %q+D", decl);
+ {
+ if (! TREE_USED (decl))
+ warning (OPT_Wunused_variable, "unused variable %q+D", decl);
+ else if (DECL_CONTEXT (decl) == current_function_decl
+ && TREE_TYPE (decl) != error_mark_node
+ && TREE_CODE (TREE_TYPE (decl)) != REFERENCE_TYPE
+ && errorcount == unused_but_set_errorcount
+ && (!CLASS_TYPE_P (TREE_TYPE (decl))
+ || !TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (decl))))
+ {
+ warning (OPT_Wunused_but_set_variable,
+ "variable %q+D set but not used", decl);
+ unused_but_set_errorcount = errorcount;
+ }
+ }
/* Remove declarations for all the DECLs in this level. */
for (link = decls; link; link = TREE_CHAIN (link))
if (DECL_VIRTUAL_P (newdecl))
DECL_THUNKS (newdecl) = DECL_THUNKS (olddecl);
}
+ /* Only variables have this field. */
+ else if (TREE_CODE (newdecl) == VAR_DECL
+ && VAR_HAD_UNKNOWN_BOUND (olddecl))
+ SET_VAR_HAD_UNKNOWN_BOUND (newdecl);
}
if (TREE_CODE (newdecl) == FUNCTION_DECL)
TREE_USED (newdecl) = 1;
else if (TREE_USED (newdecl))
TREE_USED (olddecl) = 1;
+ if (TREE_CODE (newdecl) == VAR_DECL)
+ {
+ if (DECL_READ_P (olddecl))
+ DECL_READ_P (newdecl) = 1;
+ else if (DECL_READ_P (newdecl))
+ DECL_READ_P (olddecl) = 1;
+ }
if (DECL_PRESERVE_P (olddecl))
DECL_PRESERVE_P (newdecl) = 1;
else if (DECL_PRESERVE_P (newdecl))
tree void_ftype;
tree void_ftype_ptr;
- build_common_tree_nodes (flag_signed_char, false);
+ build_common_tree_nodes (flag_signed_char);
/* Create all the identifiers we need. */
initialize_predefined_identifiers ();
/* C++ extensions */
- unknown_type_node = make_node (UNKNOWN_TYPE);
+ unknown_type_node = make_node (LANG_TYPE);
record_unknown_type (unknown_type_node, "unknown type");
/* Indirecting an UNKNOWN_TYPE node yields an UNKNOWN_TYPE node. */
TYPE_POINTER_TO (unknown_type_node) = unknown_type_node;
TYPE_REFERENCE_TO (unknown_type_node) = unknown_type_node;
- init_list_type_node = make_node (UNKNOWN_TYPE);
+ init_list_type_node = make_node (LANG_TYPE);
record_unknown_type (init_list_type_node, "init list");
{
push_cp_library_fn (VEC_NEW_EXPR, newtype);
global_delete_fndecl = push_cp_library_fn (DELETE_EXPR, deltype);
push_cp_library_fn (VEC_DELETE_EXPR, deltype);
+
+ nullptr_type_node = make_node (LANG_TYPE);
+ TYPE_SIZE (nullptr_type_node) = bitsize_int (GET_MODE_BITSIZE (ptr_mode));
+ TYPE_SIZE_UNIT (nullptr_type_node) = size_int (GET_MODE_SIZE (ptr_mode));
+ TYPE_UNSIGNED (nullptr_type_node) = 1;
+ TYPE_PRECISION (nullptr_type_node) = GET_MODE_BITSIZE (ptr_mode);
+ SET_TYPE_MODE (nullptr_type_node, Pmode);
+ record_builtin_type (RID_MAX, "decltype(nullptr)", nullptr_type_node);
+ nullptr_node = make_node (INTEGER_CST);
+ TREE_TYPE (nullptr_node) = nullptr_type_node;
}
abort_fndecl
static void
check_for_uninitialized_const_var (tree decl)
{
- tree type = TREE_TYPE (decl);
+ tree type = strip_array_types (TREE_TYPE (decl));
if (TREE_CODE (decl) == VAR_DECL && DECL_DECLARED_CONSTEXPR_P (decl)
&& DECL_INITIAL (decl) == NULL)
else if (TREE_CODE (decl) == VAR_DECL
&& TREE_CODE (type) != REFERENCE_TYPE
&& CP_TYPE_CONST_P (type)
- && !TYPE_NEEDS_CONSTRUCTING (type)
+ && (!TYPE_NEEDS_CONSTRUCTING (type)
+ || !type_has_user_provided_default_constructor (type))
&& !DECL_INITIAL (decl))
- error ("uninitialized const %qD", decl);
-}
+ {
+ permerror (DECL_SOURCE_LOCATION (decl),
+ "uninitialized const %qD", decl);
+
+ if (CLASS_TYPE_P (type)
+ && !type_has_user_provided_default_constructor (type))
+ {
+ tree defaulted_ctor;
+ inform (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (type)),
+ "%q#T has no user-provided default constructor", type);
+ defaulted_ctor = in_class_defaulted_default_constructor (type);
+ if (defaulted_ctor)
+ inform (DECL_SOURCE_LOCATION (defaulted_ctor),
+ "constructor is not user-provided because it is "
+ "explicitly defaulted in the class body");
+ }
+ }
+}
\f
/* Structure holding the current initializer being processed by reshape_init.
CUR is a pointer to the current element being processed, END is a pointer
initialized. If there are no more such fields, the return value
will be NULL. */
-static tree
+tree
next_initializable_field (tree field)
{
while (field
{
tree type = TREE_TYPE (decl);
tree init_code = NULL;
+ tree core_type;
/* Things that are going to be initialized need to have complete
type. */
else if (DECL_EXTERNAL (decl))
;
else if (TYPE_P (type) && TYPE_NEEDS_CONSTRUCTING (type))
- return build_aggr_init_full_exprs (decl, init, flags);
- else if (MAYBE_CLASS_TYPE_P (type))
{
- tree core_type = strip_array_types (type);
-
- if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type))
- error ("structure %qD with uninitialized const members", decl);
- if (CLASSTYPE_REF_FIELDS_NEED_INIT (core_type))
- error ("structure %qD with uninitialized reference members", decl);
+ check_for_uninitialized_const_var (decl);
+ return build_aggr_init_full_exprs (decl, init, flags);
+ }
+ else if (MAYBE_CLASS_TYPE_P (core_type = strip_array_types (type)))
+ {
+ if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type)
+ || CLASSTYPE_REF_FIELDS_NEED_INIT (core_type))
+ diagnose_uninitialized_cst_or_ref_member (core_type, /*using_new=*/false,
+ /*complain=*/true);
check_for_uninitialized_const_var (decl);
}
if (was_readonly)
TREE_READONLY (decl) = 1;
-
- /* If this was marked 'used', be sure it will be output. */
- if (lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
- mark_decl_referenced (decl);
}
/* Returns a declaration for a VAR_DECL as if:
parmdecl = cp_build_parm_decl (NULL_TREE, ptr_type_node);
DECL_CONTEXT (parmdecl) = fndecl;
TREE_USED (parmdecl) = 1;
+ DECL_READ_P (parmdecl) = 1;
DECL_ARGUMENTS (fndecl) = parmdecl;
}
if (in_namespace)
set_decl_namespace (decl, in_namespace, friendp);
else if (!ctype)
- DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
+ DECL_CONTEXT (decl) = FROB_CONTEXT (current_decl_namespace ());
/* `main' and builtins have implicit 'C' linkage. */
if ((MAIN_NAME_P (declarator)
/* Allow this; it's pretty common in C. */;
else
{
- permerror (input_location, "non-local function %q#D uses anonymous type",
- decl);
+ permerror (input_location, "anonymous type with no linkage "
+ "used to declare function %q#D with linkage",
+ decl);
if (DECL_ORIGINAL_TYPE (TYPE_NAME (t)))
permerror (input_location, "%q+#D does not refer to the unqualified "
"type, so it is not used for linkage",
}
}
else
- permerror (input_location, "non-local function %q#D uses local type %qT", decl, t);
+ permerror (input_location, "type %qT with no linkage used to "
+ "declare function %q#D with linkage", t, decl);
}
}
/* An explicit "extern" specifier indicates a namespace-scope
variable. */
if (declspecs->storage_class == sc_extern)
- scope = current_namespace;
+ scope = current_decl_namespace ();
else if (!at_function_scope_p ())
scope = current_scope ();
}
no linkage can only be used to declare extern "C"
entities. Since it's not always an error in the
ISO C++ 90 Standard, we only issue a warning. */
- warning (0, "non-local variable %q#D uses anonymous type",
- decl);
+ warning (0, "anonymous type with no linkage used to declare "
+ "variable %q#D with linkage", decl);
if (DECL_ORIGINAL_TYPE (TYPE_NAME (t)))
warning (0, "%q+#D does not refer to the unqualified "
"type, so it is not used for linkage",
}
}
else
- warning (0, "non-local variable %q#D uses local type %qT", decl, t);
+ warning (0, "type %qT with no linkage used to declare variable "
+ "%q#D with linkage", t, decl);
}
}
else
/* The size might be the result of a cast. */
STRIP_TYPE_NOPS (size);
+ size = mark_rvalue_use (size);
+
/* It might be a const variable or enumeration constant. */
size = integral_constant_value (size);
+ if (error_operand_p (size))
+ return error_mark_node;
/* Normally, the array-bound will be a constant. */
if (TREE_CODE (size) == INTEGER_CST)
|| operator_code == ARRAY_REF
|| operator_code == NOP_EXPR)
{
- if (class_type && LAMBDA_TYPE_P (class_type))
- /* Lambdas can have static op() and conv ops. */;
- else
- {
- error ("%qD must be a nonstatic member function", decl);
- return false;
- }
+ error ("%qD must be a nonstatic member function", decl);
+ return false;
}
else
{
tree maxnode;
tree value;
tree t;
- bool unsignedp;
- bool use_short_enum;
- int lowprec;
- int highprec;
- int precision;
- unsigned int itk;
tree underlying_type = NULL_TREE;
bool fixed_underlying_type_p
= ENUM_UNDERLYING_TYPE (enumtype) != NULL_TREE;
the enumeration had a single enumerator with value 0. */
minnode = maxnode = integer_zero_node;
- /* Compute the number of bits require to represent all values of the
- enumeration. We must do this before the type of MINNODE and
- MAXNODE are transformed, since tree_int_cst_min_precision relies
- on the TREE_TYPE of the value it is passed. */
- unsignedp = tree_int_cst_sgn (minnode) >= 0;
- lowprec = tree_int_cst_min_precision (minnode, unsignedp);
- highprec = tree_int_cst_min_precision (maxnode, unsignedp);
- precision = MAX (lowprec, highprec);
-
if (!fixed_underlying_type_p)
{
+ /* Compute the number of bits require to represent all values of the
+ enumeration. We must do this before the type of MINNODE and
+ MAXNODE are transformed, since tree_int_cst_min_precision relies
+ on the TREE_TYPE of the value it is passed. */
+ bool unsignedp = tree_int_cst_sgn (minnode) >= 0;
+ int lowprec = tree_int_cst_min_precision (minnode, unsignedp);
+ int highprec = tree_int_cst_min_precision (maxnode, unsignedp);
+ int precision = MAX (lowprec, highprec);
+ unsigned int itk;
+ bool use_short_enum;
+
/* Determine the underlying type of the enumeration.
[dcl.enum]
The value of sizeof() applied to an enumeration type, an object
of an enumeration type, or an enumerator, is the value of sizeof()
applied to the underlying type. */
+ TYPE_MIN_VALUE (enumtype) = TYPE_MIN_VALUE (underlying_type);
+ TYPE_MAX_VALUE (enumtype) = TYPE_MAX_VALUE (underlying_type);
TYPE_SIZE (enumtype) = TYPE_SIZE (underlying_type);
TYPE_SIZE_UNIT (enumtype) = TYPE_SIZE_UNIT (underlying_type);
SET_TYPE_MODE (enumtype, TYPE_MODE (underlying_type));
+ TYPE_PRECISION (enumtype) = TYPE_PRECISION (underlying_type);
TYPE_ALIGN (enumtype) = TYPE_ALIGN (underlying_type);
TYPE_USER_ALIGN (enumtype) = TYPE_USER_ALIGN (underlying_type);
TYPE_UNSIGNED (enumtype) = TYPE_UNSIGNED (underlying_type);
- /* Set the underlying type of the enumeration type to the
- computed enumeration type, restricted to the enumerator
- values. */
+ /* Compute the minimum and maximum values for the type.
+
+ [dcl.enum]
+
+ For an enumeration where emin is the smallest enumerator and emax
+ is the largest, the values of the enumeration are the values of the
+ underlying type in the range bmin to bmax, where bmin and bmax are,
+ respectively, the smallest and largest values of the smallest bit-
+ field that can store emin and emax. */
+
+ /* The middle-end currently assumes that types with TYPE_PRECISION
+ narrower than their underlying type are suitably zero or sign
+ extended to fill their mode. Similarly, it assumes that the front
+ end assures that a value of a particular type must be within
+ TYPE_MIN_VALUE and TYPE_MAX_VALUE.
+
+ We used to set these fields based on bmin and bmax, but that led
+ to invalid assumptions like optimizing away bounds checking. So
+ now we just set the TYPE_PRECISION, TYPE_MIN_VALUE, and
+ TYPE_MAX_VALUE to the values for the mode above and only restrict
+ the ENUM_UNDERLYING_TYPE for the benefit of diagnostics. */
ENUM_UNDERLYING_TYPE (enumtype)
= build_distinct_type_copy (underlying_type);
- set_min_and_max_values_for_integral_type
+ TYPE_PRECISION (ENUM_UNDERLYING_TYPE (enumtype)) = precision;
+ set_min_and_max_values_for_integral_type
(ENUM_UNDERLYING_TYPE (enumtype), precision, unsignedp);
+
+ /* If -fstrict-enums, still constrain TYPE_MIN/MAX_VALUE. */
+ if (flag_strict_enums)
+ set_min_and_max_values_for_integral_type (enumtype, precision,
+ unsignedp);
}
else
underlying_type = ENUM_UNDERLYING_TYPE (enumtype);
- /* Compute the minimum and maximum values for the type.
-
- [dcl.enum]
-
- For an enumeration where emin is the smallest enumerator and emax
- is the largest, the values of the enumeration are the values of the
- underlying type in the range bmin to bmax, where bmin and bmax are,
- respectively, the smallest and largest values of the smallest bit-
- field that can store emin and emax. */
-
- /* The middle-end currently assumes that types with TYPE_PRECISION
- narrower than their underlying type are suitably zero or sign
- extended to fill their mode. g++ doesn't make these guarantees.
- Until the middle-end can represent such paradoxical types, we
- set the TYPE_PRECISION to the width of the underlying type. */
- TYPE_PRECISION (enumtype) = TYPE_PRECISION (underlying_type);
-
- set_min_and_max_values_for_integral_type (enumtype, precision, unsignedp);
-
/* Convert each of the enumerators to the type of the underlying
type of the enumeration. */
for (values = TYPE_VALUES (enumtype); values; values = TREE_CHAIN (values))
if ((DECL_DECLARED_INLINE_P (decl1)
|| DECL_TEMPLATE_INSTANTIATION (decl1))
- && ! DECL_INTERFACE_KNOWN (decl1)
- /* Don't try to defer nested functions for now. */
- && ! decl_function_context (decl1))
+ && ! DECL_INTERFACE_KNOWN (decl1))
DECL_DEFER_OUTPUT (decl1) = 1;
else
DECL_INTERFACE_KNOWN (decl1) = 1;
info for the epilogue. */
cfun->function_end_locus = input_location;
+ /* Complain about parameters that are only set, but never otherwise used. */
+ if (warn_unused_but_set_parameter
+ && !processing_template_decl
+ && errorcount == unused_but_set_errorcount
+ && !DECL_CLONED_FUNCTION_P (fndecl))
+ {
+ tree decl;
+
+ for (decl = DECL_ARGUMENTS (fndecl);
+ decl;
+ decl = TREE_CHAIN (decl))
+ if (TREE_USED (decl)
+ && TREE_CODE (decl) == PARM_DECL
+ && !DECL_READ_P (decl)
+ && DECL_NAME (decl)
+ && !DECL_ARTIFICIAL (decl)
+ && !TREE_NO_WARNING (decl)
+ && !DECL_IN_SYSTEM_HEADER (decl)
+ && TREE_TYPE (decl) != error_mark_node
+ && TREE_CODE (TREE_TYPE (decl)) != REFERENCE_TYPE
+ && (!CLASS_TYPE_P (TREE_TYPE (decl))
+ || !TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (decl))))
+ warning (OPT_Wunused_but_set_parameter,
+ "parameter %q+D set but not used", decl);
+ unused_but_set_errorcount = errorcount;
+ }
+
/* Genericize before inlining. */
if (!processing_template_decl)
{