/* 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"
#include "output.h"
#include "except.h"
#include "toplev.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.
/* The chain of decls was accumulated in reverse order.
Put it into forward order, just for cleanliness. */
tree decls;
- int tmp = functionbody;
- int real_functionbody;
tree subblocks;
tree block;
tree decl;
gcc_assert (current_binding_level->kind != sk_class);
- real_functionbody = (current_binding_level->kind == sk_cleanup
- ? ((functionbody = 0), tmp) : functionbody);
+ if (current_binding_level->kind == sk_cleanup)
+ functionbody = 0;
subblocks = functionbody >= 0 ? current_binding_level->blocks : 0;
gcc_assert (!VEC_length(cp_class_binding,
= 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))
void
warn_extern_redeclared_static (tree newdecl, tree olddecl)
{
- tree name;
-
if (TREE_CODE (newdecl) == TYPE_DECL
|| TREE_CODE (newdecl) == TEMPLATE_DECL
|| TREE_CODE (newdecl) == CONST_DECL
&& DECL_ARTIFICIAL (olddecl))
return;
- name = DECL_ASSEMBLER_NAME (newdecl);
permerror (input_location, "%qD was declared %<extern%> and later %<static%>", newdecl);
permerror (input_location, "previous declaration of %q+D", olddecl);
}
bad choice of name. */
if (! TREE_PUBLIC (newdecl))
{
- warning (OPT_Wshadow, "shadowing %s function %q#D",
- DECL_BUILT_IN (olddecl) ? "built-in" : "library",
- olddecl);
+ warning (OPT_Wshadow,
+ DECL_BUILT_IN (olddecl)
+ ? G_("shadowing built-in function %q#D")
+ : G_("shadowing library function %q#D"), olddecl);
/* Discard the old built-in function. */
return NULL_TREE;
}
olddecl);
}
else
- warning (OPT_Wshadow, "shadowing %s function %q#D",
- DECL_BUILT_IN (olddecl) ? "built-in" : "library",
- olddecl);
+ warning (OPT_Wshadow,
+ DECL_BUILT_IN (olddecl)
+ ? G_("shadowing built-in function %q#D")
+ : G_("shadowing library function %q#D"), olddecl);
}
else
/* Discard the old built-in function. */
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))
+ DECL_PRESERVE_P (olddecl) = 1;
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
if (same_type_p (TREE_TYPE (newdecl), TREE_TYPE (olddecl)))
return NULL;
else
- return "redefinition of %q#D";
+ return G_("redefinition of %q#D");
}
else if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
if (DECL_NAMESPACE_SCOPE_P (olddecl)
&& DECL_CONTEXT (olddecl) != DECL_CONTEXT (newdecl)
&& ! decls_match (olddecl, newdecl))
- return "%qD conflicts with used function";
+ return G_("%qD conflicts with used function");
/* We'll complain about linkage mismatches in
warn_extern_redeclared_static. */
&& DECL_INITIAL (newdecl) != NULL_TREE)
{
if (DECL_NAME (olddecl) == NULL_TREE)
- return "%q#D not declared in class";
+ return G_("%q#D not declared in class");
else if (!GNU_INLINE_P (olddecl)
|| GNU_INLINE_P (newdecl))
- return "redefinition of %q#D";
+ return G_("redefinition of %q#D");
}
if (DECL_DECLARED_INLINE_P (olddecl) && DECL_DECLARED_INLINE_P (newdecl))
if (olda != newa)
{
if (newa)
- return "%q+D redeclared inline with %<gnu_inline%> attribute";
+ return G_("%q+D redeclared inline with "
+ "%<gnu_inline%> attribute");
else
- return "%q+D redeclared inline without %<gnu_inline%> attribute";
+ return G_("%q+D redeclared inline without "
+ "%<gnu_inline%> attribute");
}
}
{
if (COMPLETE_TYPE_P (TREE_TYPE (newdecl))
&& COMPLETE_TYPE_P (TREE_TYPE (olddecl)))
- return "redefinition of %q#D";
+ return G_("redefinition of %q#D");
return NULL;
}
ot = DECL_TEMPLATE_RESULT (template_for_substitution (ot));
if (DECL_INITIAL (nt) && DECL_INITIAL (ot)
&& (!GNU_INLINE_P (ot) || GNU_INLINE_P (nt)))
- return "redefinition of %q#D";
+ return G_("redefinition of %q#D");
if (DECL_DECLARED_INLINE_P (ot) && DECL_DECLARED_INLINE_P (nt))
{
if (olda != newa)
{
if (newa)
- return "%q+D redeclared inline with %<gnu_inline%> attribute";
+ return G_("%q+D redeclared inline with "
+ "%<gnu_inline%> attribute");
else
- return "%q+D redeclared inline without %<gnu_inline%> attribute";
+ return G_("%q+D redeclared inline without "
+ "%<gnu_inline%> attribute");
}
}
&& !check_default_tmpl_args (nt, DECL_TEMPLATE_PARMS (newdecl),
/*is_primary=*/1, /*is_partial=*/0,
/*is_friend_decl=*/2))
- return "redeclaration of friend %q#D may not have default template arguments";
+ return G_("redeclaration of friend %q#D "
+ "may not have default template arguments");
return NULL;
}
/* Only variables can be thread-local, and all declarations must
agree on this property. */
if (DECL_THREAD_LOCAL_P (newdecl))
- return "thread-local declaration of %q#D follows "
- "non-thread-local declaration";
+ return G_("thread-local declaration of %q#D follows "
+ "non-thread-local declaration");
else
- return "non-thread-local declaration of %q#D follows "
- "thread-local declaration";
+ return G_("non-thread-local declaration of %q#D follows "
+ "thread-local declaration");
}
else if (toplevel_bindings_p () || DECL_NAMESPACE_SCOPE_P (newdecl))
{
is invalid. */
if ((TREE_CODE (newdecl) == VAR_DECL && DECL_ANON_UNION_VAR_P (newdecl))
|| (TREE_CODE (olddecl) == VAR_DECL && DECL_ANON_UNION_VAR_P (olddecl)))
- return "redeclaration of %q#D";
+ return G_("redeclaration of %q#D");
/* If at least one declaration is a reference, there is no
conflict. For example:
if (DECL_EXTERNAL (newdecl) || DECL_EXTERNAL (olddecl))
return NULL;
/* Reject two definitions. */
- return "redefinition of %q#D";
+ return G_("redefinition of %q#D");
}
else
{
/* Reject two definitions, and reject a definition
together with an external reference. */
if (!(DECL_EXTERNAL (newdecl) && DECL_EXTERNAL (olddecl)))
- return "redeclaration of %q#D";
+ return G_("redeclaration of %q#D");
return NULL;
}
}
if (!dependent_scope_p (context))
/* We should only set WANT_TYPE when we're a nested typename type.
Then we can give better diagnostics if we find a non-type. */
- t = lookup_field (context, name, 0, /*want_type=*/true);
+ t = lookup_field (context, name, 2, /*want_type=*/true);
else
t = NULL_TREE;
- if (!t && dependent_type_p (context))
+ if ((!t || TREE_CODE (t) == TREE_LIST) && dependent_type_p (context))
return build_typename_type (context, name, fullname, tag_type);
want_template = TREE_CODE (fullname) == TEMPLATE_ID_EXPR;
return error_mark_node;
}
+ /* Pull out the template from an injected-class-name (or multiple). */
+ if (want_template)
+ t = maybe_get_template_decl_from_type_decl (t);
+
+ if (TREE_CODE (t) == TREE_LIST)
+ {
+ if (complain & tf_error)
+ {
+ error ("lookup of %qT in %qT is ambiguous", name, context);
+ print_candidates (t);
+ }
+ return error_mark_node;
+ }
+
if (want_template && !DECL_CLASS_TEMPLATE_P (t))
{
if (complain & tf_error)
if (complain & tf_error)
perform_or_defer_access_check (TYPE_BINFO (context), t, t);
+ /* If we are currently parsing a template and if T is a typedef accessed
+ through CONTEXT then we need to remember and check access of T at
+ template instantiation time. */
+ add_typedef_to_current_template_for_access_check (t, context, input_location);
+
if (want_template)
return lookup_template_class (t, TREE_OPERAND (fullname, 1),
NULL_TREE, context,
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
tree *pushed_scope_p)
{
tree decl;
- tree type;
tree context;
bool was_public;
int flags;
|| decl == error_mark_node)
return error_mark_node;
- type = TREE_TYPE (decl);
-
context = DECL_CONTEXT (decl);
if (context)
/* Don't mess with __FUNCTION__. */
&& ! DECL_ARTIFICIAL (decl)
&& DECL_FUNCTION_SCOPE_P (decl)
- && vague_linkage_fn_p (DECL_CONTEXT (decl)))
+ && vague_linkage_p (DECL_CONTEXT (decl)))
{
if (flag_weak)
{
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
field_init = reshape_init_r (TREE_TYPE (field), d,
/*first_initializer_p=*/false);
+ if (field_init == error_mark_node)
+ return error_mark_node;
+
CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (new_init), field, field_init);
/* [dcl.init.aggr]
init = error_mark_node;
}
else
- maybe_warn_cpp0x ("extended initializer lists");
+ maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
}
d->cur++;
{
tree type = TREE_TYPE (decl);
tree init_code = NULL;
+ tree core_type;
/* Things that are going to be initialized need to have complete
type. */
{
if (init_len == 0)
{
- maybe_warn_cpp0x ("extended initializer lists");
+ maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
init = build_zero_init (type, NULL_TREE, false);
}
else if (init_len != 1)
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 (DECL_FUNCTION_SCOPE_P (decl)
&& TREE_STATIC (decl)
&& !DECL_ARTIFICIAL (decl))
- push_local_name (decl);
+ {
+ push_local_name (decl);
+ if (DECL_CONSTRUCTOR_P (current_function_decl)
+ || DECL_DESTRUCTOR_P (current_function_decl))
+ /* Normally local_decls is populated during GIMPLE lowering,
+ but [cd]tors are never actually compiled directly. We need
+ to put statics on the list so we can deal with the label
+ address extension. */
+ cfun->local_decls = tree_cons (NULL_TREE, decl,
+ cfun->local_decls);
+ }
+
/* Convert the initializer to the type of DECL, if we have not
already initialized DECL. */
if (!DECL_INITIALIZED_P (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;
}
}
gcc_assert (TREE_CODE (fns) == IDENTIFIER_NODE
|| TREE_CODE (fns) == OVERLOAD);
- DECL_TEMPLATE_INFO (decl) = tree_cons (fns, args, NULL_TREE);
+ DECL_TEMPLATE_INFO (decl) = build_template_info (fns, args);
for (t = TYPE_ARG_TYPES (TREE_TYPE (decl)); t; t = TREE_CHAIN (t))
if (TREE_PURPOSE (t)
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
structural equality checks. */
itype = build_index_type (build_min (MINUS_EXPR, sizetype,
size, integer_one_node));
- if (!TREE_SIDE_EFFECTS (size))
- {
- TYPE_DEPENDENT_P (itype) = 1;
- TYPE_DEPENDENT_P_VALID (itype) = 1;
- }
+ TYPE_DEPENDENT_P (itype) = 1;
+ TYPE_DEPENDENT_P_VALID (itype) = 1;
SET_TYPE_STRUCTURAL_EQUALITY (itype);
return itype;
}
/* 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)
create_array_type_for_decl (tree name, tree type, tree size)
{
tree itype = NULL_TREE;
- const char* error_msg;
/* If things have already gone awry, bail now. */
if (type == error_mark_node || size == error_mark_node)
return error_mark_node;
- /* Assume that everything will go OK. */
- error_msg = NULL;
-
- /* There are some types which cannot be array elements. */
+ /* If there are some types which cannot be array elements,
+ issue an error-message and return. */
switch (TREE_CODE (type))
{
case VOID_TYPE:
- error_msg = "array of void";
- break;
+ if (name)
+ error ("declaration of %qD as array of void", name);
+ else
+ error ("creating array of void");
+ return error_mark_node;
case FUNCTION_TYPE:
- error_msg = "array of functions";
- break;
+ if (name)
+ error ("declaration of %qD as array of functions", name);
+ else
+ error ("creating array of functions");
+ return error_mark_node;
case REFERENCE_TYPE:
- error_msg = "array of references";
- break;
+ if (name)
+ error ("declaration of %qD as array of references", name);
+ else
+ error ("creating array of references");
+ return error_mark_node;
case METHOD_TYPE:
- error_msg = "array of function members";
- break;
-
- default:
- break;
- }
-
- /* If something went wrong, issue an error-message and return. */
- if (error_msg)
- {
if (name)
- error ("declaration of %qD as %s", name, error_msg);
+ error ("declaration of %qD as array of function members", name);
else
- error ("creating %s", error_msg);
-
+ error ("creating array of function members");
return error_mark_node;
+
+ default:
+ break;
}
/* [dcl.array]
try to parse.
PARM for a parameter declaration (either within a function prototype
or before a function body). Make a PARM_DECL, or return void_type_node.
+ TPARM for a template parameter declaration.
CATCHPARM for a parameter declaration before a catch clause.
TYPENAME if for a typename (in a cast or sizeof).
Don't make a DECL node; just return the ..._TYPE node.
FIELD for a struct or union field; make a FIELD_DECL.
BITFIELD for a field with specified width.
+
INITIALIZED is as for start_decl.
ATTRLIST is a pointer to the list of attributes, which may be NULL
bool type_was_error_mark_node = false;
bool parameter_pack_p = declarator? declarator->parameter_pack_p : false;
bool template_type_arg = false;
+ bool template_parm_flag = false;
bool constexpr_p = declspecs->specs[(int) ds_constexpr];
const char *errmsg;
bitfield = 1, decl_context = FIELD;
else if (decl_context == TEMPLATE_TYPE_ARG)
template_type_arg = true, decl_context = TYPENAME;
+ else if (decl_context == TPARM)
+ template_parm_flag = true, decl_context = PARM;
if (initialized > 1)
funcdef_flag = true;
/* This was an error in C++98 (cv-qualifiers cannot be added to
a function type), but DR 295 makes the code well-formed by
dropping the extra qualifiers. */
- if (pedantic)
+ if (pedantic && cxx_dialect == cxx98)
{
tree bad_type = build_qualified_type (type, type_quals);
pedwarn (input_location, OPT_pedantic,
error ("typedef declaration invalid in parameter declaration");
return error_mark_node;
}
+ else if (template_parm_flag && storage_class != sc_none)
+ {
+ error ("storage class specified for template parameter %qs", name);
+ return error_mark_node;
+ }
else if (storage_class == sc_static
|| storage_class == sc_extern
|| thread_p)
{
if (explicitp == 1)
{
- maybe_warn_cpp0x ("explicit conversion operators");
+ maybe_warn_cpp0x (CPP0X_EXPLICIT_CONVERSION);
explicitp = 2;
}
}
if (TREE_CODE (type) == FUNCTION_TYPE
&& cp_type_quals (type) != TYPE_UNQUALIFIED)
- error ("cannot declare %s to qualified function type %qT",
- declarator->kind == cdk_reference ? "reference" : "pointer",
+ error (declarator->kind == cdk_reference
+ ? G_("cannot declare reference to qualified function type %qT")
+ : G_("cannot declare pointer to qualified function type %qT"),
type);
if (declarator->kind == cdk_reference)
membership class as `constexpr'. */
if (constexpr_p)
error ("a constexpr function cannot be defined "
- "outside of its class.");
+ "outside of its class");
if (TREE_CODE (sname) == IDENTIFIER_NODE
&& NEW_DELETE_OPNAME_P (sname))
/* The qualifiers on the function type become the qualifiers on
the non-static member function. */
memfn_quals |= cp_type_quals (type);
+ type_quals = TYPE_UNQUALIFIED;
}
}
&& TREE_DEPRECATED (TYPE_NAME (type)))
return type;
+ /* Do warn about using typedefs to a deprecated class. */
+ if (TAGGED_TYPE_P (type) && type != TYPE_MAIN_VARIANT (type))
+ return type_is_deprecated (TYPE_MAIN_VARIANT (type));
+
code = TREE_CODE (type);
if (code == POINTER_TYPE || code == REFERENCE_TYPE
t = TREE_TYPE (t);
}
if (TREE_CODE (t) == ARRAY_TYPE)
- error ("parameter %qD includes %s to array of unknown "
- "bound %qT",
- decl, ptr ? "pointer" : "reference", t);
+ error (ptr
+ ? G_("parameter %qD includes pointer to array of "
+ "unknown bound %qT")
+ : G_("parameter %qD includes reference to array of "
+ "unknown bound %qT"),
+ decl, t);
}
if (any_error)
|| 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 t = TREE_TYPE (name);
int ref = (TREE_CODE (t) == REFERENCE_TYPE);
- const char *what = 0;
if (ref)
t = TYPE_MAIN_VARIANT (TREE_TYPE (t));
if (TREE_CODE (t) == VOID_TYPE)
- what = "void";
+ warning (OPT_Wconversion,
+ ref
+ ? G_("conversion to a reference to void "
+ "will never use a type conversion operator")
+ : G_("conversion to void "
+ "will never use a type conversion operator"));
else if (class_type)
{
if (t == class_type)
- what = "the same type";
+ warning (OPT_Wconversion,
+ ref
+ ? G_("conversion to a reference to the same type "
+ "will never use a type conversion operator")
+ : G_("conversion to the same type "
+ "will never use a type conversion operator"));
/* Don't force t to be complete here. */
else if (MAYBE_CLASS_TYPE_P (t)
&& COMPLETE_TYPE_P (t)
&& DERIVED_FROM_P (t, class_type))
- what = "a base class";
+ warning (OPT_Wconversion,
+ ref
+ ? G_("conversion to a reference to a base class "
+ "will never use a type conversion operator")
+ : G_("conversion to a base class "
+ "will never use a type conversion operator"));
}
- if (what)
- warning (OPT_Wconversion, "conversion to %s%s will never use a type "
- "conversion operator",
- ref ? "a reference to " : "", what);
}
if (operator_code == COND_EXPR)
elaborated type specifier is the implicit typedef created when
the type is declared. */
else if (!DECL_IMPLICIT_TYPEDEF_P (decl)
+ && !DECL_SELF_REFERENCE_P (decl)
&& tag_code != typename_type)
{
error ("using typedef-name %qD after %qs", decl, tag_name (tag_code));
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))
gcc_assert (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE);
cp_function_chain->x_current_class_ref
- = cp_build_indirect_ref (t, NULL, tf_warning_or_error);
+ = cp_build_indirect_ref (t, RO_NULL, tf_warning_or_error);
cp_function_chain->x_current_class_ptr = t;
/* Constructors and destructors need to know whether they're "in
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;
&& !current_function_returns_value && !current_function_returns_null
/* Don't complain if we abort or throw. */
&& !current_function_returns_abnormally
+ /* Don't complain if we are declared noreturn. */
+ && !TREE_THIS_VOLATILE (fndecl)
&& !DECL_NAME (DECL_RESULT (fndecl))
&& !TREE_NO_WARNING (fndecl)
/* Structor return values (if any) are set by the compiler. */
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)
{
struct language_function *f = DECL_SAVED_FUNCTION_DATA (fndecl);
- invoke_plugin_callbacks (PLUGIN_CXX_CP_PRE_GENERICIZE, fndecl);
+ invoke_plugin_callbacks (PLUGIN_PRE_GENERICIZE, fndecl);
cp_genericize (fndecl);
/* Clear out the bits we don't need. */
f->x_current_class_ptr = NULL;
{
}
+/* Return the FUNCTION_TYPE that corresponds to MEMFNTYPE, which can be a
+ FUNCTION_DECL, METHOD_TYPE, FUNCTION_TYPE, pointer or reference to
+ METHOD_TYPE or FUNCTION_TYPE, or pointer to member function. */
+
+tree
+static_fn_type (tree memfntype)
+{
+ tree fntype;
+ tree args;
+ int quals;
+
+ if (TYPE_PTRMEMFUNC_P (memfntype))
+ memfntype = TYPE_PTRMEMFUNC_FN_TYPE (memfntype);
+ if (POINTER_TYPE_P (memfntype)
+ || TREE_CODE (memfntype) == FUNCTION_DECL)
+ memfntype = TREE_TYPE (memfntype);
+ if (TREE_CODE (memfntype) == FUNCTION_TYPE)
+ return memfntype;
+ gcc_assert (TREE_CODE (memfntype) == METHOD_TYPE);
+ args = TYPE_ARG_TYPES (memfntype);
+ fntype = build_function_type (TREE_TYPE (memfntype), TREE_CHAIN (args));
+ quals = cp_type_quals (TREE_TYPE (TREE_VALUE (args)));
+ fntype = build_qualified_type (fntype, quals);
+ fntype = (cp_build_type_attribute_variant
+ (fntype, TYPE_ATTRIBUTES (memfntype)));
+ fntype = (build_exception_variant
+ (fntype, TYPE_RAISES_EXCEPTIONS (memfntype)));
+ return fntype;
+}
+
/* DECL was originally constructed as a non-static member function,
but turned out to be static. Update it accordingly. */
void
revert_static_member_fn (tree decl)
{
- tree tmp;
- tree function = TREE_TYPE (decl);
- tree args = TYPE_ARG_TYPES (function);
+ TREE_TYPE (decl) = static_fn_type (decl);
- if (cp_type_quals (TREE_TYPE (TREE_VALUE (args)))
- != TYPE_UNQUALIFIED)
+ if (cp_type_quals (TREE_TYPE (decl)) != TYPE_UNQUALIFIED)
error ("static member function %q#D declared with type qualifiers", decl);
- args = TREE_CHAIN (args);
- tmp = build_function_type (TREE_TYPE (function), args);
- tmp = build_qualified_type (tmp, cp_type_quals (function));
- tmp = build_exception_variant (tmp,
- TYPE_RAISES_EXCEPTIONS (function));
- TREE_TYPE (decl) = tmp;
if (DECL_ARGUMENTS (decl))
DECL_ARGUMENTS (decl) = TREE_CHAIN (DECL_ARGUMENTS (decl));
DECL_STATIC_FUNCTION_P (decl) = 1;
case ARGUMENT_PACK_SELECT: return TS_CP_ARGUMENT_PACK_SELECT;
case TRAIT_EXPR: return TS_CP_TRAIT_EXPR;
case LAMBDA_EXPR: return TS_CP_LAMBDA_EXPR;
+ case TEMPLATE_INFO: return TS_CP_TEMPLATE_INFO;
default: return TS_CP_GENERIC;
}
}