#include "tm_p.h"
#include "target.h"
#include "c-family/c-common.h"
+#include "c-family/c-objc.h"
#include "c-family/c-pragma.h"
#include "diagnostic.h"
#include "intl.h"
{
tree decl;
- for (decl = ent->names_in_scope; decl; decl = DECL_CHAIN (decl))
+ /* ENT->NAMES_IN_SCOPE may contain a mixture of DECLs and
+ TREE_LISTs representing OVERLOADs, so be careful. */
+ for (decl = ent->names_in_scope; decl; decl = (DECL_P (decl)
+ ? DECL_CHAIN (decl)
+ : TREE_CHAIN (decl)))
if (decl_jump_unsafe (decl))
VEC_safe_push (tree, gc, ent->bad_decls, decl);
if (same_type_p (TREE_TYPE (f1), TREE_TYPE (f2)))
{
- if (p2 == NULL_TREE && DECL_EXTERN_C_P (olddecl)
+ if (!prototype_p (f2) && DECL_EXTERN_C_P (olddecl)
&& (DECL_BUILT_IN (olddecl)
#ifndef NO_IMPLICIT_EXTERN_C
|| (DECL_IN_SYSTEM_HEADER (newdecl) && !DECL_CLASS_SCOPE_P (newdecl))
TREE_TYPE (newdecl) = TREE_TYPE (olddecl);
}
#ifndef NO_IMPLICIT_EXTERN_C
- else if (p1 == NULL_TREE
+ else if (!prototype_p (f1)
&& (DECL_EXTERN_C_P (olddecl)
&& DECL_IN_SYSTEM_HEADER (olddecl)
&& !DECL_CLASS_SCOPE_P (olddecl))
}
#endif
else
- types_match = compparms (p1, p2);
+ types_match =
+ compparms (p1, p2)
+ && (TYPE_ATTRIBUTES (TREE_TYPE (newdecl)) == NULL_TREE
+ || targetm.comp_type_attributes (TREE_TYPE (newdecl),
+ TREE_TYPE (olddecl)) != 0);
}
else
types_match = 0;
}
else if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_INITIAL (olddecl) != NULL_TREE
- && TYPE_ARG_TYPES (TREE_TYPE (olddecl)) == NULL_TREE
- && TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != NULL_TREE)
+ && !prototype_p (TREE_TYPE (olddecl))
+ && prototype_p (TREE_TYPE (newdecl)))
{
/* Prototype decl follows defn w/o prototype. */
warning_at (input_location, 0, "prototype for %q+#D", newdecl);
return error_mark_node;
if (low_value)
- low_value = decl_constant_value (low_value);
+ low_value = cxx_constant_value (low_value);
if (high_value)
- high_value = decl_constant_value (high_value);
+ high_value = cxx_constant_value (high_value);
r = c_add_case_label (loc, switch_stack->cases, cond,
SWITCH_STMT_TYPE (switch_stack->switch_stmt),
if (MAYBE_CLASS_TYPE_P (context))
tmpl = lookup_field (context, name, 0, false);
+ if (tmpl && TREE_CODE (tmpl) == TYPE_DECL)
+ tmpl = maybe_get_template_decl_from_type_decl (tmpl);
+
if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
{
if (complain & tf_error)
{
tree type, decl;
if (size > 0)
- type = build_nonstandard_integer_type (size, 0);
+ {
+ type = build_nonstandard_integer_type (size, 0);
+ type = build_distinct_type_copy (type);
+ }
else if (size > -32)
{
tree stype;
/* "__java_char" or ""__java_boolean". */
type = build_nonstandard_integer_type (-size, 1);
+ type = build_distinct_type_copy (type);
/* Get the signed type cached and attached to the unsigned type,
so it doesn't get garbage-collected at "random" times,
causing potential codegen differences out of different UIDs
and different alias set numbers. */
stype = build_nonstandard_integer_type (-size, 0);
+ stype = build_distinct_type_copy (stype);
TREE_CHAIN (type) = stype;
/*if (size == -1) TREE_SET_CODE (type, BOOLEAN_TYPE);*/
}
if (current_function_decl)
{
struct cp_binding_level *b = current_binding_level;
+ if (b->kind == sk_function_parms)
+ return error_mark_node;
while (b->level_chain->kind != sk_function_parms)
b = b->level_chain;
pushdecl_with_scope (decl, b, /*is_friend=*/false);
grok_reference_init. */
static tree
-build_init_list_var_init (tree decl, tree type, tree init, tree *cleanup)
+build_init_list_var_init (tree decl, tree type, tree init, tree *array_init,
+ tree *cleanup)
{
tree aggr_init, array, arrtype;
init = perform_implicit_conversion (type, init, tf_warning_or_error);
return error_mark_node;
aggr_init = TARGET_EXPR_INITIAL (init);
- init = build2 (INIT_EXPR, type, decl, init);
-
array = AGGR_INIT_EXPR_ARG (aggr_init, 1);
arrtype = TREE_TYPE (array);
STRIP_NOPS (array);
static variable and we don't need to do anything here. */
if (decl && TREE_CODE (array) == TARGET_EXPR)
{
- tree subinit;
- tree var = set_up_extended_ref_temp (decl, array, cleanup, &subinit);
+ tree var = set_up_extended_ref_temp (decl, array, cleanup, array_init);
var = build_address (var);
var = convert (arrtype, var);
AGGR_INIT_EXPR_ARG (aggr_init, 1) = var;
- init = build2 (COMPOUND_EXPR, TREE_TYPE (init), subinit, init);
}
return init;
}
/* An automatic variable with an incomplete type: that is an error.
Don't talk about array types here, since we took care of that
message in grokdeclarator. */
- error ("storage size of %qD isn't known", decl);
+ error ("storage size of %qD isn%'t known", decl);
TREE_TYPE (decl) = error_mark_node;
}
#if 0
constant_expression_warning (DECL_SIZE (decl));
else
{
- error ("storage size of %qD isn't constant", decl);
+ error ("storage size of %qD isn%'t constant", decl);
TREE_TYPE (decl) = error_mark_node;
}
}
DECL_COMMON (decl) = 0;
warning_at (input_location, 0,
"sorry: semantics of inline function static "
- "data %q+#D are wrong (you'll wind up "
+ "data %q+#D are wrong (you%'ll wind up "
"with multiple copies)", decl);
warning_at (DECL_SOURCE_LOCATION (decl), 0,
" you can work around this by removing "
{
tree type = TREE_TYPE (decl);
tree init_code = NULL;
+ tree extra_init = NULL_TREE;
tree core_type;
/* Things that are going to be initialized need to have complete
gcc_assert (init != NULL_TREE);
init = NULL_TREE;
}
- else if (!DECL_EXTERNAL (decl) && TREE_CODE (type) == REFERENCE_TYPE)
+ else if (!init && DECL_REALLY_EXTERN (decl))
+ ;
+ else if (TREE_CODE (type) == REFERENCE_TYPE)
init = grok_reference_init (decl, type, init, cleanup);
- else if (init)
+ else if (init || TYPE_NEEDS_CONSTRUCTING (type))
{
+ if (!init)
+ check_for_uninitialized_const_var (decl);
/* Do not reshape constructors of vectors (they don't need to be
reshaped. */
- if (BRACE_ENCLOSED_INITIALIZER_P (init))
+ else if (BRACE_ENCLOSED_INITIALIZER_P (init))
{
if (is_std_init_list (type))
- return build_init_list_var_init (decl, type, init, cleanup);
+ init = build_init_list_var_init (decl, type, init,
+ &extra_init, cleanup);
else if (TYPE_NON_AGGREGATE_CLASS (type))
{
/* Don't reshape if the class has constructors. */
if (TYPE_NEEDS_CONSTRUCTING (type)
|| (CLASS_TYPE_P (type)
- && !BRACE_ENCLOSED_INITIALIZER_P (init)))
- return build_aggr_init_full_exprs (decl, init, flags);
- else if (TREE_CODE (init) != TREE_VEC)
+ && !(init && BRACE_ENCLOSED_INITIALIZER_P (init))))
+ {
+ init_code = build_aggr_init_full_exprs (decl, init, flags);
+
+ /* If this is a constexpr initializer, expand_default_init will
+ have returned an INIT_EXPR rather than a CALL_EXPR. In that
+ case, pull the initializer back out and pass it down into
+ store_init_value. */
+ while (TREE_CODE (init_code) == EXPR_STMT
+ || TREE_CODE (init_code) == CONVERT_EXPR)
+ init_code = TREE_OPERAND (init_code, 0);
+ if (TREE_CODE (init_code) == INIT_EXPR)
+ {
+ init = TREE_OPERAND (init_code, 1);
+ init_code = NULL_TREE;
+ /* Don't call digest_init; it's unnecessary and will complain
+ about aggregate initialization of non-aggregate classes. */
+ flags |= LOOKUP_ALREADY_DIGESTED;
+ }
+ else if (DECL_DECLARED_CONSTEXPR_P (decl))
+ {
+ /* Declared constexpr, but no suitable initializer; massage
+ init appropriately so we can pass it into store_init_value
+ for the error. */
+ if (init && BRACE_ENCLOSED_INITIALIZER_P (init))
+ init = finish_compound_literal (type, init);
+ else if (CLASS_TYPE_P (type)
+ && (!init || TREE_CODE (init) == TREE_LIST))
+ {
+ init = build_functional_cast (type, init, tf_none);
+ if (init != error_mark_node)
+ TARGET_EXPR_DIRECT_INIT_P (init) = true;
+ }
+ init_code = NULL_TREE;
+ }
+ else
+ init = NULL_TREE;
+ }
+
+ if (init && TREE_CODE (init) != TREE_VEC)
{
init_code = store_init_value (decl, init, flags);
if (pedantic && TREE_CODE (type) == ARRAY_TYPE
init = NULL;
}
}
- else if (DECL_EXTERNAL (decl))
- ;
- else if (TYPE_P (type) && TYPE_NEEDS_CONSTRUCTING (type))
- {
- 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)))
+ else
{
- if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type)
- || CLASSTYPE_REF_FIELDS_NEED_INIT (core_type))
+ if (CLASS_TYPE_P (core_type = strip_array_types (type))
+ && (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);
}
- else
- check_for_uninitialized_const_var (decl);
if (init && init != error_mark_node)
init_code = build2 (INIT_EXPR, type, decl, init);
+ if (extra_init)
+ init_code = add_stmt_to_compound (extra_init, init_code);
+
+ if (init_code && DECL_IN_AGGR_P (decl))
+ {
+ static int explained = 0;
+
+ if (cxx_dialect < cxx0x)
+ error ("initializer invalid for static member with constructor");
+ else
+ error ("non-constant in-class initialization invalid for static "
+ "member %qD", decl);
+ if (!explained)
+ {
+ error ("(an out of class initialization is required)");
+ explained = 1;
+ }
+ }
+
return init_code;
}
if (TREE_CODE (d_init) == TREE_LIST)
d_init = build_x_compound_expr_from_list (d_init, ELK_INIT,
tf_warning_or_error);
+ d_init = resolve_nondeduced_context (d_init);
if (describable_type (d_init))
{
type = TREE_TYPE (decl) = do_auto_deduction (type, d_init,
DECL_INITIAL (decl) = NULL_TREE;
}
}
-
+
+ if (init && TREE_CODE (decl) == VAR_DECL)
+ {
+ DECL_NONTRIVIALLY_INITIALIZED_P (decl) = 1;
+ /* FIXME we rely on TREE_CONSTANT below; basing that on
+ init_const_expr_p is probably wrong for C++0x. */
+ if (init_const_expr_p)
+ {
+ /* Set these flags now for C++98 templates. We'll update the
+ flags in store_init_value for instantiations and C++0x. */
+ DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = 1;
+ if (decl_maybe_constant_var_p (decl))
+ TREE_CONSTANT (decl) = 1;
+ }
+ }
+
if (processing_template_decl)
{
bool type_dependent_p;
DECL_INITIAL (decl) = NULL_TREE;
}
- if (init && init_const_expr_p && TREE_CODE (decl) == VAR_DECL)
- {
- DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = 1;
- if (DECL_INTEGRAL_CONSTANT_VAR_P (decl))
- TREE_CONSTANT (decl) = 1;
- }
-
/* Generally, initializers in templates are expanded when the
- template is instantiated. But, if DECL is an integral
- constant static data member, then it can be used in future
- integral constant expressions, and its value must be
- available. */
+ template is instantiated. But, if DECL is a variable constant
+ then it can be used in future constant expressions, so its value
+ must be available. */
if (!(init
&& DECL_CLASS_SCOPE_P (decl)
- && DECL_INTEGRAL_CONSTANT_VAR_P (decl)
+ /* We just set TREE_CONSTANT appropriately; see above. */
+ && TREE_CONSTANT (decl)
&& !type_dependent_p
+ /* FIXME non-value-dependent constant expression */
&& !value_dependent_init_p (init)))
{
if (init)
error ("Java object %qD not allocated with %<new%>", decl);
init = NULL_TREE;
}
- if (init)
- {
- DECL_NONTRIVIALLY_INITIALIZED_P (decl) = 1;
- if (init_const_expr_p)
- {
- DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = 1;
- if (DECL_INTEGRAL_CONSTANT_VAR_P (decl))
- TREE_CONSTANT (decl) = 1;
- }
- }
init = check_initializer (decl, init, flags, &cleanup);
/* Thread-local storage cannot be dynamically initialized. */
if (DECL_THREAD_LOCAL_P (decl) && init)
{
/* An out-of-class default definition is defined at
the point where it is explicitly defaulted. */
- if (DECL_INITIAL (decl) == error_mark_node)
+ if (DECL_DELETED_FN (decl))
+ maybe_explain_implicit_delete (decl);
+ else if (DECL_INITIAL (decl) == error_mark_node)
synthesize_method (decl);
}
else
gcc_assert (TREE_CODE (decl) == VAR_DECL);
gcc_assert (TREE_STATIC (decl));
- /* Some variables require no initialization. */
+ /* Some variables require no dynamic initialization. */
if (!init
- && !TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
&& TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
return;
name of the thing being declared. */
tree
-compute_array_index_type (tree name, tree size)
+compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
{
tree type;
tree itype;
+ tree osize = size;
tree abi_1_itype = NULL_TREE;
if (error_operand_p (size))
return error_mark_node;
type = TREE_TYPE (size);
- /* The array bound must be an integer type. */
- if (!dependent_type_p (type) && !INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type))
+ /* type_dependent_expression_p? */
+ if (!dependent_type_p (type))
{
- if (name)
- error ("size of array %qD has non-integral type %qT", name, type);
+ mark_rvalue_use (size);
+
+ if (cxx_dialect < cxx0x && TREE_CODE (size) == NOP_EXPR
+ && TREE_SIDE_EFFECTS (size))
+ /* In C++98, we mark a non-constant array bound with a magic
+ NOP_EXPR with TREE_SIDE_EFFECTS; don't fold in that case. */;
else
- error ("size of array has non-integral type %qT", type);
- size = integer_one_node;
- type = TREE_TYPE (size);
+ {
+ size = fold_non_dependent_expr (size);
+
+ if (CLASS_TYPE_P (type)
+ && CLASSTYPE_LITERAL_P (type))
+ {
+ size = build_expr_type_conversion (WANT_INT, size, true);
+ if (size == error_mark_node)
+ return error_mark_node;
+ type = TREE_TYPE (size);
+ }
+
+ size = maybe_constant_value (size);
+ }
+
+ if (error_operand_p (size))
+ return error_mark_node;
+
+ /* The array bound must be an integer type. */
+ if (!INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type))
+ {
+ if (!(complain & tf_error))
+ return error_mark_node;
+ if (name)
+ error ("size of array %qD has non-integral type %qT", name, type);
+ else
+ error ("size of array has non-integral type %qT", type);
+ size = integer_one_node;
+ type = TREE_TYPE (size);
+ }
}
/* A type is dependent if it is...an array type constructed from any
dependent type or whose size is specified by a constant expression
that is value-dependent. */
/* We can only call value_dependent_expression_p on integral constant
- expressions; the parser adds a dummy NOP_EXPR with TREE_SIDE_EFFECTS
- set if this isn't one. */
+ expressions; treat non-constant expressions as dependent, too. */
if (processing_template_decl
&& (dependent_type_p (type)
- || TREE_SIDE_EFFECTS (size) || value_dependent_expression_p (size)))
+ || !TREE_CONSTANT (size) || value_dependent_expression_p (size)))
{
/* We cannot do any checking for a SIZE that isn't known to be
constant. Just build the index type and mark that it requires
would have, but with TYPE_CANONICAL set to the "right"
value that the current ABI would provide. */
abi_1_itype = build_index_type (build_min (MINUS_EXPR, sizetype,
- size, integer_one_node));
-
- /* 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;
+ osize, integer_one_node));
/* Normally, the array-bound will be a constant. */
if (TREE_CODE (size) == INTEGER_CST)
/* An array must have a positive number of elements. */
if (INT_CST_LT (size, integer_zero_node))
{
+ if (!(complain & tf_error))
+ return error_mark_node;
if (name)
error ("size of array %qD is negative", name);
else
error ("size of array is negative");
size = integer_one_node;
}
- /* As an extension we allow zero-sized arrays. We always allow
- them in system headers because glibc uses them. */
- else if (integer_zerop (size) && !in_system_header)
+ /* As an extension we allow zero-sized arrays. */
+ else if (integer_zerop (size))
{
- if (name)
+ if (!(complain & tf_error))
+ /* We must fail if performing argument deduction (as
+ indicated by the state of complain), so that
+ another substitution can be found. */
+ return error_mark_node;
+ else if (in_system_header)
+ /* Allow them in system headers because glibc uses them. */;
+ else if (name)
pedwarn (input_location, OPT_pedantic, "ISO C++ forbids zero-size array %qD", name);
else
pedwarn (input_location, OPT_pedantic, "ISO C++ forbids zero-size array");
}
}
- else if (TREE_CONSTANT (size))
+ else if (TREE_CONSTANT (size)
+ /* We don't allow VLAs at non-function scopes, or during
+ tentative template substitution. */
+ || !at_function_scope_p () || !(complain & tf_error))
{
+ if (!(complain & tf_error))
+ return error_mark_node;
/* `(int) &fn' is not a valid array bound. */
if (name)
error ("size of array %qD is not an integral constant-expression",
else if (TREE_CODE (itype) == INTEGER_CST
&& TREE_OVERFLOW (itype))
{
+ if (!(complain & tf_error))
+ return error_mark_node;
error ("overflow in array dimension");
TREE_OVERFLOW (itype) = 0;
}
/* Figure out the index type for the array. */
if (size)
- itype = compute_array_index_type (name, size);
+ itype = compute_array_index_type (name, size, tf_warning_or_error);
/* [dcl.array]
T is called the array element type; this type shall not be [...] an
else if (friendp)
{
if (initialized)
- error ("can't initialize friend function %qs", name);
+ error ("can%'t initialize friend function %qs", name);
if (virtualp)
{
/* Cannot be both friend and virtual. */
if (decl_context == NORMAL)
error ("friend declaration not in class definition");
if (current_function_decl && funcdef_flag)
- error ("can't define friend function %qs in a local "
+ error ("can%'t define friend function %qs in a local "
"class definition",
name);
}
error ("const %qs cannot be declared %<mutable%>", name);
storage_class = sc_none;
}
+ else if (TREE_CODE (type) == REFERENCE_TYPE)
+ {
+ permerror (input_location, "reference %qs cannot be declared "
+ "%<mutable%>", name);
+ storage_class = sc_none;
+ }
}
/* If this is declaring a typedef name, return a TYPE_DECL. */
if (!staticp && TREE_CODE (type) == ARRAY_TYPE
&& TYPE_DOMAIN (type) == NULL_TREE)
{
- tree itype = compute_array_index_type (dname, integer_zero_node);
+ tree itype = compute_array_index_type (dname, integer_zero_node,
+ tf_warning_or_error);
type = build_cplus_array_type (TREE_TYPE (type), itype);
}
if (friendp == 0)
{
- gcc_assert (ctype);
+ /* This should never happen in pure C++ (the check
+ could be an assert). It could happen in
+ Objective-C++ if someone writes invalid code that
+ uses a function declaration for an instance
+ variable or property (instance variables and
+ properties are parsed as FIELD_DECLs, but they are
+ part of an Objective-C class, not a C++ class).
+ That code is invalid and is caught by this
+ check. */
+ if (!ctype)
+ {
+ error ("declaration of function %qD in invalid context",
+ unqualified_id);
+ return error_mark_node;
+ }
/* ``A union may [ ... ] not [ have ] virtual functions.''
ARM 9.5 */
if (thread_p)
DECL_TLS_MODEL (decl) = decl_default_tls_model (decl);
+
+ if (constexpr_p && !initialized)
+ {
+ error ("constexpr static data member %qD must have an "
+ "initializer", decl);
+ constexpr_p = false;
+ }
}
else
{
/* Validate and default VALUE. */
if (value != NULL_TREE)
{
- value = integral_constant_value (value);
+ value = cxx_constant_value (value);
if (TREE_CODE (value) == INTEGER_CST)
{
value = perform_integral_promotions (value);
- constant_expression_warning (value);
}
else
{
if (fndecl == NULL_TREE)
return error_mark_node;
+ if (c_dialect_objc ())
+ objc_finish_function ();
+
gcc_assert (!defer_mark_used_calls);
defer_mark_used_calls = true;
if (DECL_IN_AGGR_P (fndecl))
{
- if (DECL_CONTEXT (fndecl)
- && TREE_CODE (DECL_CONTEXT (fndecl)) != NAMESPACE_DECL)
+ if (DECL_CLASS_SCOPE_P (fndecl))
error ("%qD is already defined in class %qT", fndecl,
DECL_CONTEXT (fndecl));
return error_mark_node;