/* 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 "coretypes.h"
#include "tm.h"
#include "tree.h"
-#include "rtl.h"
-#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 "hashtab.h"
#include "tm_p.h"
#include "target.h"
-#include "c-common.h"
-#include "c-pragma.h"
+#include "c-family/c-common.h"
+#include "c-family/c-pragma.h"
#include "diagnostic.h"
#include "intl.h"
#include "debug.h"
#include "timevar.h"
#include "tree-flow.h"
#include "pointer-set.h"
+#include "splay-tree.h"
#include "plugin.h"
static tree grokparms (tree parmlist, tree *);
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 ((pedantic || ! DECL_IN_SYSTEM_HEADER (old_decl))
&& ! DECL_IS_BUILTIN (old_decl)
&& flag_exceptions
- && !comp_except_specs (new_exceptions, old_exceptions,
- /*exact=*/true))
+ && !comp_except_specs (new_exceptions, old_exceptions, ce_normal))
{
- error ("declaration of %qF throws different exceptions", new_decl);
+ error ("declaration of %qF has a different exception specifier",
+ new_decl);
error ("from previous declaration %q+F", old_decl);
}
}
/* Even if the types match, prefer the new declarations type for
built-ins which have not been explicitly declared, for
exception lists, etc... */
- else if (DECL_ANTICIPATED (olddecl))
+ else if (DECL_SOURCE_LOCATION (olddecl) == BUILTINS_LOCATION)
{
tree type = TREE_TYPE (newdecl);
tree attribs = (*targetm.merge_type_attributes)
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;
}
}
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 ();
truthvalue_true_node = boolean_true_node;
empty_except_spec = build_tree_list (NULL_TREE, NULL_TREE);
+ noexcept_true_spec = build_tree_list (boolean_true_node, NULL_TREE);
+ noexcept_false_spec = build_tree_list (boolean_false_node, NULL_TREE);
#if 0
record_builtin_type (RID_MAX, NULL, string_type_node);
/* 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");
{
vtbl_type_node
= build_cplus_array_type (vtable_entry_type, NULL_TREE);
layout_type (vtbl_type_node);
- vtbl_type_node = build_qualified_type (vtbl_type_node, TYPE_QUAL_CONST);
+ vtbl_type_node = cp_build_qualified_type (vtbl_type_node, TYPE_QUAL_CONST);
record_builtin_type (RID_MAX, NULL, vtbl_type_node);
vtbl_ptr_type_node = build_pointer_type (vtable_entry_type);
layout_type (vtbl_ptr_type_node);
current_lang_name = lang_name_cplusplus;
{
- tree bad_alloc_id;
- tree bad_alloc_type_node;
- tree bad_alloc_decl;
tree newtype, deltype;
tree ptr_ftype_sizetype;
-
- push_namespace (std_identifier);
- bad_alloc_id = get_identifier ("bad_alloc");
- bad_alloc_type_node = make_class_type (RECORD_TYPE);
- TYPE_CONTEXT (bad_alloc_type_node) = current_namespace;
- bad_alloc_decl
- = create_implicit_typedef (bad_alloc_id, bad_alloc_type_node);
- DECL_CONTEXT (bad_alloc_decl) = current_namespace;
- pop_namespace ();
+ tree new_eh_spec;
ptr_ftype_sizetype
= build_function_type (ptr_type_node,
tree_cons (NULL_TREE,
size_type_node,
void_list_node));
- newtype = build_exception_variant
- (ptr_ftype_sizetype, add_exception_specifier
- (NULL_TREE, bad_alloc_type_node, -1));
+ if (cxx_dialect == cxx98)
+ {
+ tree bad_alloc_id;
+ tree bad_alloc_type_node;
+ tree bad_alloc_decl;
+
+ push_namespace (std_identifier);
+ bad_alloc_id = get_identifier ("bad_alloc");
+ bad_alloc_type_node = make_class_type (RECORD_TYPE);
+ TYPE_CONTEXT (bad_alloc_type_node) = current_namespace;
+ bad_alloc_decl
+ = create_implicit_typedef (bad_alloc_id, bad_alloc_type_node);
+ DECL_CONTEXT (bad_alloc_decl) = current_namespace;
+ pop_namespace ();
+
+ new_eh_spec
+ = add_exception_specifier (NULL_TREE, bad_alloc_type_node, -1);
+ }
+ else
+ new_eh_spec = noexcept_false_spec;
+
+ newtype = build_exception_variant (ptr_ftype_sizetype, new_eh_spec);
deltype = build_exception_variant (void_ftype_ptr, empty_except_spec);
push_cp_library_fn (NEW_EXPR, newtype);
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
init = build_string (length + 1, name);
}
- type = build_qualified_type (char_type_node, TYPE_QUAL_CONST);
+ type = cp_build_qualified_type (char_type_node, TYPE_QUAL_CONST);
type = build_cplus_array_type (type, domain);
*type_p = type;
/* This is a const variable with implicit 'static'. Set
DECL_THIS_STATIC so we can tell it from variables that are
!TREE_PUBLIC because of the anonymous namespace. */
- gcc_assert (cp_type_readonly (TREE_TYPE (decl)));
+ gcc_assert (CP_TYPE_CONST_P (TREE_TYPE (decl)));
DECL_THIS_STATIC (decl) = 1;
}
/* 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
{
tree type = TREE_TYPE (decl);
tree init_code = NULL;
+ tree core_type;
/* Things that are going to be initialized need to have complete
type. */
error ("in C++98 %qD must be initialized by constructor, "
"not by %<{...}%>",
decl);
- init = build_tree_list (NULL_TREE, init);
}
else if (TREE_CODE (type) == VECTOR_TYPE && TYPE_VECTOR_OPAQUE (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);
}
/* DECL is a VAR_DECL for a compiler-generated variable with static
storage duration (like a virtual table) whose initializer is a
- compile-time constant. INIT must be either a TREE_LIST of values,
- or a CONSTRUCTOR. Initialize the variable and provide it to the
+ compile-time constant. Initialize the variable and provide it to the
back end. */
void
-initialize_artificial_var (tree decl, tree init)
+initialize_artificial_var (tree decl, VEC(constructor_elt,gc) *v)
{
+ tree init;
gcc_assert (DECL_ARTIFICIAL (decl));
- if (TREE_CODE (init) == TREE_LIST)
- init = build_constructor_from_list (TREE_TYPE (decl), init);
+ init = build_constructor (TREE_TYPE (decl), v);
gcc_assert (TREE_CODE (init) == CONSTRUCTOR);
DECL_INITIAL (decl) = init;
DECL_INITIALIZED_P (decl) = 1;
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;
}
{
tree cleanup;
tree compound_stmt;
- tree args;
tree fcall;
tree type;
bool use_dtor;
+ tree arg0, arg1 = NULL_TREE, arg2 = NULL_TREE;
type = TREE_TYPE (decl);
if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
in, and, in general, it's cheaper to pass NULL than any
other value. */
addr = null_pointer_node;
- args = tree_cons (NULL_TREE,
- cp_build_unary_op (ADDR_EXPR, get_dso_handle_node (), 0,
- tf_warning_or_error),
- NULL_TREE);
+ arg2 = cp_build_unary_op (ADDR_EXPR, get_dso_handle_node (), 0,
+ tf_warning_or_error);
if (targetm.cxx.use_aeabi_atexit ())
{
- args = tree_cons (NULL_TREE, cleanup, args);
- args = tree_cons (NULL_TREE, addr, args);
+ arg1 = cleanup;
+ arg0 = addr;
}
else
{
- args = tree_cons (NULL_TREE, addr, args);
- args = tree_cons (NULL_TREE, cleanup, args);
+ arg1 = addr;
+ arg0 = cleanup;
}
}
else
- args = tree_cons (NULL_TREE, cleanup, NULL_TREE);
- return cp_build_function_call (get_atexit_node (), args,
- tf_warning_or_error);
+ arg0 = cleanup;
+ return cp_build_function_call_nary (get_atexit_node (), tf_warning_or_error,
+ arg0, arg1, arg2, NULL_TREE);
}
/* DECL is a VAR_DECL with static storage duration. INIT, if present,
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
{
if (TREE_CODE (member_type) == METHOD_TYPE)
{
- tree arg_types = TYPE_ARG_TYPES (member_type);
- cp_cv_quals quals = cp_type_quals (TREE_TYPE (TREE_VALUE (arg_types)));
+ cp_cv_quals quals = type_memfn_quals (member_type);
member_type = build_memfn_type (member_type, class_type, quals);
return build_ptrmemfunc_type (build_pointer_type (member_type));
}
/* 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)
{
tree type = NULL_TREE;
int longlong = 0;
+ int explicit_int128 = 0;
int virtualp, explicitp, friendp, inlinep, staticp;
int explicit_int = 0;
int explicit_char = 0;
short_p = declspecs->specs[(int)ds_short];
long_p = declspecs->specs[(int)ds_long];
longlong = declspecs->specs[(int)ds_long] >= 2;
+ explicit_int128 = declspecs->explicit_int128_p;
thread_p = declspecs->specs[(int)ds_thread];
if (decl_context == FUNCDEF)
if (long_p && !longlong && TYPE_MAIN_VARIANT (type) == double_type_node)
{
long_p = false;
- type = build_qualified_type (long_double_type_node,
- cp_type_quals (type));
+ type = cp_build_qualified_type (long_double_type_node,
+ cp_type_quals (type));
}
/* Check all other uses of type modifiers. */
error ("%<signed%> and %<unsigned%> specified together for %qs", name);
else if (longlong && TREE_CODE (type) != INTEGER_TYPE)
error ("%<long long%> invalid for %qs", name);
+ else if (explicit_int128 && TREE_CODE (type) != INTEGER_TYPE)
+ error ("%<__int128%> invalid for %qs", name);
else if (long_p && TREE_CODE (type) == REAL_TYPE)
error ("%<long%> invalid for %qs", name);
else if (short_p && TREE_CODE (type) == REAL_TYPE)
error ("%<short%> invalid for %qs", name);
else if ((long_p || short_p) && TREE_CODE (type) != INTEGER_TYPE)
error ("%<long%> or %<short%> invalid for %qs", name);
+ else if ((long_p || short_p || explicit_char || explicit_int) && explicit_int128)
+ error ("%<long%>, %<int%>, %<short%>, or %<char%> invalid for %qs", name);
else if ((long_p || short_p) && explicit_char)
error ("%<long%> or %<short%> specified with char for %qs", name);
else if (long_p && short_p)
else
{
ok = 1;
- if (!explicit_int && !defaulted_int && !explicit_char && pedantic)
+ if (!explicit_int && !defaulted_int && !explicit_char && !explicit_int128 && pedantic)
{
pedwarn (input_location, OPT_pedantic,
"long, short, signed or unsigned used invalidly for %qs",
if (flag_pedantic_errors)
ok = 0;
}
+ if (explicit_int128)
+ {
+ if (int128_integer_type_node == NULL_TREE)
+ {
+ error ("%<__int128%> is not supported by this target");
+ ok = 0;
+ }
+ else if (pedantic)
+ {
+ pedwarn (input_location, OPT_pedantic,
+ "ISO C++ does not support %<__int128%> for %qs",
+ name);
+ if (flag_pedantic_errors)
+ ok = 0;
+ }
+ }
}
/* Discard the type modifiers if they are invalid. */
long_p = false;
short_p = false;
longlong = 0;
+ explicit_int128 = false;
}
}
&& TREE_CODE (type) == INTEGER_TYPE
&& !same_type_p (TYPE_MAIN_VARIANT (type), wchar_type_node)))
{
- if (longlong)
+ if (explicit_int128)
+ type = int128_unsigned_type_node;
+ else if (longlong)
type = long_long_unsigned_type_node;
else if (long_p)
type = long_unsigned_type_node;
}
else if (signed_p && type == char_type_node)
type = signed_char_type_node;
+ else if (explicit_int128)
+ type = int128_integer_type_node;
else if (longlong)
type = long_long_integer_type_node;
else if (long_p)
"complex double", but if any modifiers at all are specified it is
the complex form of TYPE. E.g, "complex short" is
"complex short int". */
-
- else if (defaulted_int && ! longlong
+ else if (defaulted_int && ! longlong && ! explicit_int128
&& ! (long_p || short_p || signed_p || unsigned_p))
type = complex_double_type_node;
else if (type == integer_type_node)
error ("qualifiers are not allowed on declaration of %<operator %T%>",
ctor_return_type);
- if (TREE_CODE (type) == FUNCTION_TYPE
- && type_quals != TYPE_UNQUALIFIED)
- {
- /* 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 && cxx_dialect == cxx98)
- {
- tree bad_type = build_qualified_type (type, type_quals);
- pedwarn (input_location, OPT_pedantic,
- "ignoring %qV qualifiers added to function type %qT",
- bad_type, type);
- }
- type_quals = TYPE_UNQUALIFIED;
- }
type_quals |= cp_type_quals (type);
type = cp_build_qualified_type_real
(type, type_quals, ((typedef_decl && !DECL_ARTIFICIAL (typedef_decl)
&& (TREE_CODE (type) == FUNCTION_TYPE
|| (memfn_quals && TREE_CODE (type) == METHOD_TYPE)))
{
- memfn_quals |= cp_type_quals (type);
+ memfn_quals |= type_memfn_quals (type);
type = build_memfn_type (type,
declarator->u.pointer.class_type,
memfn_quals);
}
if (TREE_CODE (type) == FUNCTION_TYPE
- && cp_type_quals (type) != TYPE_UNQUALIFIED)
+ && type_memfn_quals (type) != TYPE_UNQUALIFIED)
error (declarator->kind == cdk_reference
? G_("cannot declare reference to qualified function type %qT")
: G_("cannot declare pointer to qualified function type %qT"),
type);
+ /* When the pointed-to type involves components of variable size,
+ care must be taken to ensure that the size evaluation code is
+ emitted early enough to dominate all the possible later uses
+ and late enough for the variables on which it depends to have
+ been assigned.
+
+ This is expected to happen automatically when the pointed-to
+ type has a name/declaration of it's own, but special attention
+ is required if the type is anonymous.
+
+ We handle the NORMAL and FIELD contexts here by inserting a
+ dummy statement that just evaluates the size at a safe point
+ and ensures it is not deferred until e.g. within a deeper
+ conditional context (c++/43555).
+
+ We expect nothing to be needed here for PARM or TYPENAME.
+ Evaluating the size at this point for TYPENAME would
+ actually be incorrect, as we might be in the middle of an
+ expression with side effects on the pointed-to type size
+ "arguments" prior to the pointer declaration point and the
+ size evaluation could end up prior to the side effects. */
+
+ if (!TYPE_NAME (type)
+ && (decl_context == NORMAL || decl_context == FIELD)
+ && at_function_scope_p ()
+ && variably_modified_type_p (type, NULL_TREE))
+ finish_expr_stmt (TYPE_SIZE (type));
+
if (declarator->kind == cdk_reference)
{
/* In C++0x, the type we are creating a reference to might be
function type. */
if (memfn_quals && TREE_CODE (type) == FUNCTION_TYPE)
{
- type = cp_build_qualified_type (type, memfn_quals);
+ type = apply_memfn_quals (type, memfn_quals);
/* We have now dealt with these qualifiers. */
memfn_quals = TYPE_UNQUALIFIED;
for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
{
if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
- {
- debug_hooks->set_name (t, decl);
- TYPE_NAME (t) = decl;
- }
+ /* We do not rename the debug info representing the
+ anonymous tagged type because the standard says in
+ [dcl.typedef] that the naming applies only for
+ linkage purposes. */
+ /*debug_hooks->set_name (t, decl);*/
+ TYPE_NAME (t) = decl;
}
if (TYPE_LANG_SPECIFIC (type))
{
/* A cv-qualifier-seq shall only be part of the function type
for a non-static member function. [8.3.5/4 dcl.fct] */
- if (cp_type_quals (type) != TYPE_UNQUALIFIED
+ if (type_memfn_quals (type) != TYPE_UNQUALIFIED
&& (current_class_type == NULL_TREE || staticp) )
{
error (staticp
/* The qualifiers on the function type become the qualifiers on
the non-static member function. */
- memfn_quals |= cp_type_quals (type);
+ memfn_quals |= type_memfn_quals (type);
type_quals = TYPE_UNQUALIFIED;
}
}
type = build_memfn_type (type, ctype, memfn_quals);
/* Core issue #547: need to allow this in template type args. */
else if (template_type_arg && TREE_CODE (type) == FUNCTION_TYPE)
- type = cp_build_qualified_type (type, memfn_quals);
+ type = apply_memfn_quals (type, memfn_quals);
else
error ("invalid qualifiers on non-member function type");
}
|| 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
{
/* The binfo slot should be empty, unless this is an (ill-formed)
redefinition. */
- gcc_assert (!TYPE_BINFO (ref) || TYPE_SIZE (ref));
+ if (TYPE_BINFO (ref) && !TYPE_SIZE (ref))
+ {
+ error ("redefinition of %q#T", ref);
+ return false;
+ }
+
gcc_assert (TYPE_MAIN_VARIANT (ref) == ref);
binfo = make_tree_binfo (max_bases);
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]
itk++)
{
underlying_type = integer_types[itk];
- if (TYPE_PRECISION (underlying_type) >= precision
+ if (underlying_type != NULL_TREE
+ && TYPE_PRECISION (underlying_type) >= precision
&& TYPE_UNSIGNED (underlying_type) == unsignedp)
break;
}
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;
{
return (flag_exceptions && flag_enforce_eh_specs
&& !processing_template_decl
- && TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn))
+ && !type_throw_all_p (TREE_TYPE (fn))
/* We insert the EH_SPEC_BLOCK only in the original
function; then, it is copied automatically to the
clones. */
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)
{
fn = lookup_name (id);
arg = build_address (decl);
mark_used (decl);
- cleanup = cp_build_function_call (fn, build_tree_list (NULL_TREE,
- arg),
- tf_warning_or_error);
+ cleanup = cp_build_function_call_nary (fn, tf_warning_or_error,
+ arg, NULL_TREE);
}
/* Handle ordinary C++ destructors. */
type = TREE_TYPE (decl);
{
tree fntype;
tree args;
- int quals;
if (TYPE_PTRMEMFUNC_P (memfntype))
memfntype = TYPE_PTRMEMFUNC_FN_TYPE (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 = apply_memfn_quals (fntype, type_memfn_quals (memfntype));
fntype = (cp_build_type_attribute_variant
(fntype, TYPE_ATTRIBUTES (memfntype)));
fntype = (build_exception_variant