-/* Process declarations and variables for C++ compiler.
- Copyright (C) 1988-2018 Free Software Foundation, Inc.
+/* Process declarations and variables for -*- C++ -*- compiler.
+ Copyright (C) 1988-2019 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GCC.
static void require_complete_types_for_parms (tree);
static tree grok_reference_init (tree, tree, tree, int);
static tree grokvardecl (tree, tree, tree, const cp_decl_specifier_seq *,
- int, int, int, bool, int, tree);
+ int, int, int, bool, int, tree, location_t);
static void check_static_variable_definition (tree, tree);
static void record_unknown_type (tree, const char *);
static tree builtin_function_1 (tree, tree, bool);
static void layout_var_decl (tree);
static tree check_initializer (tree, tree, int, vec<tree, va_gc> **);
static void make_rtl_for_nonlocal_decl (tree, tree, const char *);
-static void save_function_data (tree);
static void copy_type_enum (tree , tree);
static void check_function_type (tree, tree);
static void finish_constructor_body (void);
auto_diagnostic_group d;
if (permerror (DECL_SOURCE_LOCATION (newdecl),
"friend declaration of %q#D specifies default "
- "arguments and isn't the only declaration", newdecl))
+ "arguments and isn%'t the only declaration", newdecl))
inform (DECL_SOURCE_LOCATION (olddecl),
"previous declaration of %q#D", olddecl);
return;
if (! same_type_p (TREE_VALUE (t1), TREE_VALUE (t2)))
break;
-next_arg:;
+ next_arg:;
}
warning_at (newdecl_loc,
tree old_result = DECL_TEMPLATE_RESULT (olddecl);
tree new_result = DECL_TEMPLATE_RESULT (newdecl);
TREE_TYPE (olddecl) = TREE_TYPE (old_result);
- DECL_TEMPLATE_SPECIALIZATIONS (olddecl)
- = chainon (DECL_TEMPLATE_SPECIALIZATIONS (olddecl),
- DECL_TEMPLATE_SPECIALIZATIONS (newdecl));
+
+ /* The new decl should not already have gathered any
+ specializations. */
+ gcc_assert (!DECL_TEMPLATE_SPECIALIZATIONS (newdecl));
DECL_ATTRIBUTES (old_result)
= (*targetm.merge_decl_attributes) (old_result, new_result);
if (TYPE_NAME (TREE_TYPE (newdecl)) == newdecl)
{
tree remove = TREE_TYPE (newdecl);
- for (tree t = TYPE_MAIN_VARIANT (remove); ;
- t = TYPE_NEXT_VARIANT (t))
- if (TYPE_NEXT_VARIANT (t) == remove)
- {
- TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (remove);
- break;
- }
+ if (TYPE_MAIN_VARIANT (remove) == remove)
+ {
+ gcc_assert (TYPE_NEXT_VARIANT (remove) == NULL_TREE);
+ /* If remove is the main variant, no need to remove that
+ from the list. One of the DECL_ORIGINAL_TYPE
+ variants, e.g. created for aligned attribute, might still
+ refer to the newdecl TYPE_DECL though, so remove that one
+ in that case. */
+ if (tree orig = DECL_ORIGINAL_TYPE (newdecl))
+ if (orig != remove)
+ for (tree t = TYPE_MAIN_VARIANT (orig); t;
+ t = TYPE_MAIN_VARIANT (t))
+ if (TYPE_NAME (TYPE_NEXT_VARIANT (t)) == newdecl)
+ {
+ TYPE_NEXT_VARIANT (t)
+ = TYPE_NEXT_VARIANT (TYPE_NEXT_VARIANT (t));
+ break;
+ }
+ }
+ else
+ for (tree t = TYPE_MAIN_VARIANT (remove); ;
+ t = TYPE_NEXT_VARIANT (t))
+ if (TYPE_NEXT_VARIANT (t) == remove)
+ {
+ TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (remove);
+ break;
+ }
}
}
else if (merge_attr)
}
DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
}
- /* Only functions have these fields. */
+
if (DECL_DECLARES_FUNCTION_P (newdecl))
{
+ /* Only functions have these fields. */
DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
DECL_BEFRIENDING_CLASSES (newdecl)
= chainon (DECL_BEFRIENDING_CLASSES (newdecl),
if (DECL_VIRTUAL_P (newdecl))
SET_DECL_THUNKS (newdecl, DECL_THUNKS (olddecl));
}
- /* Only variables have this field. */
- else if (VAR_P (newdecl)
- && VAR_HAD_UNKNOWN_BOUND (olddecl))
- SET_VAR_HAD_UNKNOWN_BOUND (newdecl);
+ else if (VAR_P (newdecl))
+ {
+ /* Only variables have this field. */
+ if (VAR_HAD_UNKNOWN_BOUND (olddecl))
+ SET_VAR_HAD_UNKNOWN_BOUND (newdecl);
+ }
}
if (TREE_CODE (newdecl) == FUNCTION_DECL)
}
else if (DECL_PENDING_INLINE_P (newdecl))
;
- else if (DECL_SAVED_FUNCTION_DATA (newdecl) == NULL)
- DECL_SAVED_FUNCTION_DATA (newdecl)
- = DECL_SAVED_FUNCTION_DATA (olddecl);
+ else if (DECL_SAVED_AUTO_RETURN_TYPE (newdecl) == NULL)
+ DECL_SAVED_AUTO_RETURN_TYPE (newdecl)
+ = DECL_SAVED_AUTO_RETURN_TYPE (olddecl);
DECL_DECLARED_INLINE_P (newdecl) |= DECL_DECLARED_INLINE_P (olddecl);
{
case sk_try:
if (!saw_eh)
- inf = N_("enters try block");
+ inf = G_(" enters %<try%> block");
saw_eh = true;
break;
case sk_catch:
if (!saw_eh)
- inf = N_("enters catch block");
+ inf = G_(" enters %<catch%> block");
saw_eh = true;
break;
case sk_omp:
if (!saw_omp)
- inf = N_("enters OpenMP structured block");
+ inf = G_(" enters OpenMP structured block");
saw_omp = true;
break;
case sk_transaction:
if (!saw_tm)
- inf = N_("enters synchronized or atomic statement");
+ inf = G_(" enters synchronized or atomic statement");
saw_tm = true;
break;
case sk_block:
if (!saw_cxif && level_for_constexpr_if (b->level_chain))
{
- inf = N_("enters constexpr if statement");
+ inf = G_(" enters %<constexpr if%> statement");
loc = EXPR_LOCATION (b->level_chain->this_entity);
saw_cxif = true;
}
complained = identify_goto (decl, input_location, locus, DK_ERROR);
identified = 2;
if (complained)
- inform (loc, " %s", inf);
+ inform (loc, inf);
}
}
identified = 2;
}
if (complained)
- inform (DECL_SOURCE_LOCATION (bad), " enters catch block");
+ inform (DECL_SOURCE_LOCATION (bad), " enters %<catch%> block");
saw_catch = true;
}
else if (complained)
if (complained)
{
if (ent->in_try_scope)
- inform (input_location, " enters try block");
+ inform (input_location, " enters %<try%> block");
else if (ent->in_catch_scope && !saw_catch)
- inform (input_location, " enters catch block");
+ inform (input_location, " enters %<catch%> block");
else if (ent->in_transaction_scope)
inform (input_location, " enters synchronized or atomic statement");
else if (ent->in_constexpr_if)
- inform (input_location, " enters %<constexpr%> if statement");
+ inform (input_location, " enters %<constexpr if%> statement");
}
if (ent->in_omp_scope)
label. We need a tree, rather than simply a hash table, because
of the GNU case range extension. */
splay_tree cases;
- /* Remember whether there was a case value that is outside the
- range of the original type of the controlling expression. */
- bool outside_range_p;
/* Remember whether a default: case label has been seen. */
bool has_default_p;
/* Remember whether a BREAK_STMT has been seen in this SWITCH_STMT. */
p->next = switch_stack;
p->switch_stmt = switch_stmt;
p->cases = splay_tree_new (case_compare, NULL, NULL);
- p->outside_range_p = false;
p->has_default_p = false;
p->break_stmt_seen_p = false;
p->in_loop_body_p = false;
if (!processing_template_decl)
c_do_switch_warnings (cs->cases, switch_location,
SWITCH_STMT_TYPE (cs->switch_stmt),
- SWITCH_STMT_COND (cs->switch_stmt),
- bool_cond_p, cs->outside_range_p);
+ SWITCH_STMT_COND (cs->switch_stmt), bool_cond_p);
/* For the benefit of block_may_fallthru remember if the switch body
case labels cover all possible values and if there are break; stmts. */
low_value = case_conversion (type, low_value);
high_value = case_conversion (type, high_value);
- r = c_add_case_label (loc, switch_stack->cases, cond, type,
- low_value, high_value,
- &switch_stack->outside_range_p);
+ r = c_add_case_label (loc, switch_stack->cases, cond, low_value, high_value);
/* After labels, make any new cleanups in the function go into their
own new (temporary) binding contour. */
gcc_assert (identifier_p (name));
gcc_assert (TYPE_P (context));
- if (!MAYBE_CLASS_TYPE_P (context))
+ if (TREE_CODE (context) == TYPE_PACK_EXPANSION)
+ /* This can happen for C++17 variadic using (c++/88986). */;
+ else if (!MAYBE_CLASS_TYPE_P (context))
{
if (complain & tf_error)
error ("%q#T is not a class", context);
if (aligned_new_threshold > 1
&& !pow2p_hwi (aligned_new_threshold))
{
- error ("-faligned-new=%d is not a power of two", aligned_new_threshold);
+ error ("%<-faligned-new=%d%> is not a power of two",
+ aligned_new_threshold);
aligned_new_threshold = 1;
}
if (aligned_new_threshold == -1)
}
if (is_global)
- pushdecl_top_level (decl);
+ return pushdecl_top_level (decl);
else
- pushdecl (decl);
-
- return decl;
+ return pushdecl (decl);
}
tree
declared_type = declspecs->type;
else if (declspecs->type == error_mark_node)
error_p = true;
- if (declared_type == NULL_TREE && ! saw_friend && !error_p)
- permerror (input_location, "declaration does not declare anything");
- else if (declared_type != NULL_TREE && type_uses_auto (declared_type))
+
+ if (type_uses_auto (declared_type))
{
error_at (declspecs->locations[ds_type_spec],
"%<auto%> can only be specified for variables "
"or function declarations");
return error_mark_node;
}
+
+ if (declared_type && !OVERLOAD_TYPE_P (declared_type))
+ declared_type = NULL_TREE;
+
+ if (!declared_type && !saw_friend && !error_p)
+ permerror (input_location, "declaration does not declare anything");
/* Check for an anonymous union. */
else if (declared_type && RECORD_OR_UNION_CODE_P (TREE_CODE (declared_type))
&& TYPE_UNNAMED_P (declared_type))
if (initialized
&& TREE_CODE (decl) == TYPE_DECL)
{
- error ("typedef %qD is initialized (use decltype instead)", decl);
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "typedef %qD is initialized (use %qs instead)",
+ decl, "decltype");
return error_mark_node;
}
a definition. */
if (initialized && DECL_DLLIMPORT_P (decl))
{
- error ("definition of %q#D is marked %<dllimport%>", decl);
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "definition of %q#D is marked %<dllimport%>", decl);
DECL_DLLIMPORT_P (decl) = 0;
}
&& DECL_UNINLINABLE (decl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (decl)))
warning_at (DECL_SOURCE_LOCATION (decl), 0,
- "inline function %qD given attribute noinline", decl);
+ "inline function %qD given attribute %qs", decl, "noinline");
if (TYPE_P (context) && COMPLETE_TYPE_P (complete_type (context)))
{
if (DECL_EXTERNAL (decl) && ! DECL_TEMPLATE_SPECIALIZATION (decl)
/* Aliases are definitions. */
&& !alias)
- permerror (input_location, "declaration of %q#D outside of class is not definition",
+ permerror (declarator->id_loc,
+ "declaration of %q#D outside of class is not definition",
decl);
}
{
bool ok = false;
if (CP_DECL_THREAD_LOCAL_P (decl))
- error ("%qD declared %<thread_local%> in %<constexpr%> function",
- decl);
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "%qD declared %<thread_local%> in %<constexpr%> function",
+ decl);
else if (TREE_STATIC (decl))
- error ("%qD declared %<static%> in %<constexpr%> function", decl);
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "%qD declared %<static%> in %<constexpr%> function", decl);
else
ok = true;
if (!ok)
if ((DECL_LANG_SPECIFIC (decl) == 0
|| DECL_IN_AGGR_P (decl) == 0)
&& ! DECL_THIS_EXTERN (decl))
- error ("%qD declared as reference but not initialized", decl);
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "%qD declared as reference but not initialized", decl);
return NULL_TREE;
}
be merged. */
TREE_PUBLIC (decl) = 0;
DECL_COMMON (decl) = 0;
+ DECL_INTERFACE_KNOWN (decl) = 1;
const char *msg;
if (DECL_INLINE_VAR_P (decl))
msg = G_("sorry: semantics of inline variable "
if (!field)
return true;
+ bool show_notes = true;
+
if (!constexpr_context_p)
{
if (CP_TYPE_CONST_P (type))
{
if (complain & tf_error)
- permerror (DECL_SOURCE_LOCATION (decl),
- "uninitialized const %qD", decl);
+ show_notes = permerror (DECL_SOURCE_LOCATION (decl),
+ "uninitialized %<const %D%>", decl);
}
else
{
error_at (DECL_SOURCE_LOCATION (decl),
"uninitialized variable %qD in %<constexpr%> "
"function", decl);
+ else
+ show_notes = false;
cp_function_chain->invalid_constexpr = true;
}
}
"uninitialized variable %qD in %<constexpr%> context",
decl);
- if (CLASS_TYPE_P (type) && (complain & tf_error))
+ if (show_notes && CLASS_TYPE_P (type) && (complain & tf_error))
{
tree defaulted_ctor;
max_index_cst = tree_to_uhwi (fold_convert (size_type_node, max_index));
}
+ /* Set to the index of the last element with a non-zero initializer.
+ Zero initializers for elements past this one can be dropped. */
+ unsigned HOST_WIDE_INT last_nonzero = -1;
/* Loop until there are no more initializers. */
for (index = 0;
d->cur != d->end && (!sized_array_p || index <= max_index_cst);
if (!TREE_CONSTANT (elt_init))
TREE_CONSTANT (new_init) = false;
+ /* Pointers initialized to strings must be treated as non-zero
+ even if the string is empty. */
+ tree init_type = TREE_TYPE (elt_init);
+ if ((POINTER_TYPE_P (elt_type) != POINTER_TYPE_P (init_type))
+ || !initializer_zerop (elt_init))
+ last_nonzero = index;
+
/* This can happen with an invalid initializer (c++/54501). */
if (d->cur == old_cur && !sized_array_p)
break;
}
+ if (sized_array_p && trivial_type_p (elt_type))
+ {
+ /* Strip trailing zero-initializers from an array of a trivial
+ type of known size. They are redundant and get in the way
+ of telling them apart from those with implicit zero value. */
+ unsigned HOST_WIDE_INT nelts = CONSTRUCTOR_NELTS (new_init);
+ if (last_nonzero > nelts)
+ nelts = 0;
+ else if (last_nonzero < nelts - 1)
+ nelts = last_nonzero + 1;
+
+ vec_safe_truncate (CONSTRUCTOR_ELTS (new_init), nelts);
+ }
+
return new_init;
}
tree id = DECL_NAME (d->cur->index);
gcc_assert (id);
gcc_checking_assert (d->cur->index
- == get_class_binding (type, id, false));
+ == get_class_binding (type, id));
field = d->cur->index;
}
}
else if (TREE_CODE (d->cur->index) == IDENTIFIER_NODE)
- field = get_class_binding (type, d->cur->index, false);
+ field = get_class_binding (type, d->cur->index);
else
{
if (complain & tf_error)
&& has_designator_problem (d, complain))
return error_mark_node;
+ tree stripped_init = tree_strip_any_location_wrapper (init);
+
if (TREE_CODE (type) == COMPLEX_TYPE)
{
/* A complex type can be initialized from one or two initializers,
but braces are not elided. */
d->cur++;
- if (BRACE_ENCLOSED_INITIALIZER_P (init))
+ if (BRACE_ENCLOSED_INITIALIZER_P (stripped_init))
{
- if (CONSTRUCTOR_NELTS (init) > 2)
+ if (CONSTRUCTOR_NELTS (stripped_init) > 2)
{
if (complain & tf_error)
error ("too many initializers for %qT", type);
We need to check for BRACE_ENCLOSED_INITIALIZER_P here because
of g++.old-deja/g++.mike/p7626.C: a pointer-to-member constant is
a CONSTRUCTOR (with a record type). */
- if (TREE_CODE (init) == CONSTRUCTOR
+ if (TREE_CODE (stripped_init) == CONSTRUCTOR
/* Don't complain about a capture-init. */
- && !CONSTRUCTOR_IS_DIRECT_INIT (init)
- && BRACE_ENCLOSED_INITIALIZER_P (init)) /* p7626.C */
+ && !CONSTRUCTOR_IS_DIRECT_INIT (stripped_init)
+ && BRACE_ENCLOSED_INITIALIZER_P (stripped_init)) /* p7626.C */
{
if (SCALAR_TYPE_P (type))
{
- if (cxx_dialect < cxx11
- /* Isn't value-initialization. */
- || CONSTRUCTOR_NELTS (init) > 0)
+ if (cxx_dialect < cxx11)
{
if (complain & tf_error)
error ("braces around scalar initializer for type %qT",
type);
init = error_mark_node;
}
+ else if (first_initializer_p
+ || (CONSTRUCTOR_NELTS (stripped_init) > 0
+ && (BRACE_ENCLOSED_INITIALIZER_P
+ (CONSTRUCTOR_ELT (stripped_init,0)->value))))
+ {
+ if (complain & tf_error)
+ error ("too many braces around scalar initializer"
+ "for type %qT", type);
+ init = error_mark_node;
+ }
}
else
maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
&& char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type))))
{
tree str_init = init;
+ tree stripped_str_init = stripped_init;
/* Strip one level of braces if and only if they enclose a single
element (as allowed by [dcl.init.string]). */
if (!first_initializer_p
- && TREE_CODE (str_init) == CONSTRUCTOR
- && CONSTRUCTOR_NELTS (str_init) == 1)
+ && TREE_CODE (stripped_str_init) == CONSTRUCTOR
+ && CONSTRUCTOR_NELTS (stripped_str_init) == 1)
{
- str_init = (*CONSTRUCTOR_ELTS (str_init))[0].value;
+ str_init = (*CONSTRUCTOR_ELTS (stripped_str_init))[0].value;
+ stripped_str_init = tree_strip_any_location_wrapper (str_init);
}
/* If it's a string literal, then it's the initializer for the array
as a whole. Otherwise, continue with normal initialization for
array types (one value per array element). */
- if (TREE_CODE (str_init) == STRING_CST)
+ if (TREE_CODE (stripped_str_init) == STRING_CST)
{
if (has_designator_problem (d, complain))
return error_mark_node;
which reshape_init exists). */
if (!first_initializer_p)
{
- if (TREE_CODE (init) == CONSTRUCTOR)
+ if (TREE_CODE (stripped_init) == CONSTRUCTOR)
{
- if (TREE_TYPE (init) && TYPE_PTRMEMFUNC_P (TREE_TYPE (init)))
- /* There is no need to reshape pointer-to-member function
- initializers, as they are always constructed correctly
- by the front end. */
- ;
- else if (COMPOUND_LITERAL_P (init))
+ tree init_type = TREE_TYPE (init);
+ if (init_type && TYPE_PTRMEMFUNC_P (init_type))
+ /* There is no need to call reshape_init for pointer-to-member
+ function initializers, as they are always constructed correctly
+ by the front end. Here we have e.g. {.__pfn=0B, .__delta=0},
+ which is missing outermost braces. We should warn below, and
+ one of the routines below will wrap it in additional { }. */;
/* For a nested compound literal, there is no need to reshape since
- brace elision is not allowed. Even if we decided to allow it,
- we should add a call to reshape_init in finish_compound_literal,
- before calling digest_init, so changing this code would still
- not be necessary. */
- gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (init));
+ we called reshape_init in finish_compound_literal, before calling
+ digest_init. */
+ else if (COMPOUND_LITERAL_P (stripped_init)
+ /* Similarly, a CONSTRUCTOR of the target's type is a
+ previously digested initializer. */
+ || same_type_ignoring_top_level_qualifiers_p (type,
+ init_type))
+ {
+ ++d->cur;
+ gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (stripped_init));
+ return init;
+ }
else
{
+ /* Something that hasn't been reshaped yet. */
++d->cur;
- gcc_assert (BRACE_ENCLOSED_INITIALIZER_P (init));
+ gcc_assert (BRACE_ENCLOSED_INITIALIZER_P (stripped_init));
return reshape_init (type, init, complain);
}
}
if (CONSTRUCTOR_IS_DIRECT_INIT (init)
&& BRACE_ENCLOSED_INITIALIZER_P (new_init))
CONSTRUCTOR_IS_DIRECT_INIT (new_init) = true;
+ if (CONSTRUCTOR_IS_DESIGNATED_INIT (init)
+ && BRACE_ENCLOSED_INITIALIZER_P (new_init))
+ CONSTRUCTOR_IS_DESIGNATED_INIT (new_init) = true;
return new_init;
}
}
if (init_code
- && (DECL_IN_AGGR_P (decl)
- && DECL_INITIALIZED_IN_CLASS_P (decl)
- && !DECL_VAR_DECLARED_INLINE_P (decl)))
+ && DECL_IN_AGGR_P (decl)
+ && DECL_INITIALIZED_IN_CLASS_P (decl))
{
static int explained = 0;
external; it is only a declaration, and not a definition. */
if (init == NULL_TREE)
gcc_assert (DECL_EXTERNAL (decl)
- || !TREE_PUBLIC (decl)
- || DECL_INLINE_VAR_P (decl));
+ || !TREE_PUBLIC (decl));
}
/* We don't create any RTL for local variables. */
return;
if (TREE_CODE (type) == FUNCTION_TYPE)
{
- error ("initializer for %<decltype(auto) %D%> has function type "
- "(did you forget the %<()%> ?)", decl);
+ error ("initializer for %<decltype(auto) %D%> has function type; "
+ "did you forget the %<()%>?", decl);
TREE_TYPE (decl) = error_mark_node;
return;
}
synthesize_method (decl);
}
else
- error ("function %q#D is initialized like a variable", decl);
+ error_at (cp_expr_loc_or_loc (init,
+ DECL_SOURCE_LOCATION (decl)),
+ "function %q#D is initialized like a variable",
+ decl);
}
/* else no initialization required. */
}
&& ! (DECL_LANG_SPECIFIC (decl)
&& DECL_NOT_REALLY_EXTERN (decl)))
{
- if (init)
- DECL_INITIAL (decl) = init;
+ /* check_initializer will have done any constant initialization. */
}
/* A variable definition. */
else if (DECL_FUNCTION_SCOPE_P (decl) && !TREE_STATIC (decl))
}
else
{
- vec<tree,va_gc> *args = make_tree_vector_single (e);
+ releasing_vec args (make_tree_vector_single (e));
fns = lookup_template_function (get__identifier, targs);
fns = perform_koenig_lookup (fns, args, tf_warning_or_error);
return finish_call_expr (fns, &args, /*novirt*/false,
{
if (!processing_template_decl
&& !error_operand_p (decl)
- && DECL_NAMESPACE_SCOPE_P (decl))
+ && TREE_STATIC (decl))
{
auto_vec<tree, 16> v;
v.safe_grow (count);
DECL_HAS_VALUE_EXPR_P (v[i]) = 0;
}
if (!processing_template_decl)
- cp_finish_decl (v[i], init, /*constexpr*/false,
- /*asm*/NULL_TREE, LOOKUP_NORMAL);
+ {
+ TREE_PUBLIC (v[i]) = TREE_PUBLIC (decl);
+ TREE_STATIC (v[i]) = TREE_STATIC (decl);
+ DECL_COMMON (v[i]) = DECL_COMMON (decl);
+ DECL_COMDAT (v[i]) = DECL_COMDAT (decl);
+ if (TREE_STATIC (v[i]))
+ {
+ CP_DECL_THREAD_LOCAL_P (v[i])
+ = CP_DECL_THREAD_LOCAL_P (decl);
+ set_decl_tls_model (v[i], DECL_TLS_MODEL (decl));
+ if (DECL_ONE_ONLY (decl))
+ make_decl_one_only (v[i], cxx_comdat_group (v[i]));
+ if (TREE_PUBLIC (decl))
+ DECL_WEAK (v[i]) = DECL_WEAK (decl);
+ DECL_VISIBILITY (v[i]) = DECL_VISIBILITY (decl);
+ DECL_VISIBILITY_SPECIFIED (v[i])
+ = DECL_VISIBILITY_SPECIFIED (decl);
+ }
+ cp_finish_decl (v[i], init, /*constexpr*/false,
+ /*asm*/NULL_TREE, LOOKUP_NORMAL);
+ }
}
/* Ignore reads from the underlying decl performed during initialization
of the individual variables. If those will be read, we'll mark
if (CP_DECL_THREAD_LOCAL_P (decl) && DECL_GNU_TLS_P (decl)
&& !DECL_FUNCTION_SCOPE_P (decl))
{
+ location_t dloc = DECL_SOURCE_LOCATION (decl);
if (init)
- error ("non-local variable %qD declared %<__thread%> "
- "needs dynamic initialization", decl);
+ error_at (dloc, "non-local variable %qD declared %<__thread%> "
+ "needs dynamic initialization", decl);
else
- error ("non-local variable %qD declared %<__thread%> "
- "has a non-trivial destructor", decl);
+ error_at (dloc, "non-local variable %qD declared %<__thread%> "
+ "has a non-trivial destructor", decl);
static bool informed;
if (!informed)
{
- inform (DECL_SOURCE_LOCATION (decl),
- "C++11 %<thread_local%> allows dynamic initialization "
- "and destruction");
+ inform (dloc, "C++11 %<thread_local%> allows dynamic "
+ "initialization and destruction");
informed = true;
}
return;
{
vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (initial_value);
tree value = (*v)[0].value;
+ STRIP_ANY_LOCATION_WRAPPER (value);
if (TREE_CODE (value) == STRING_CST
&& v->length () == 1)
the information in the TEMPLATE_ID_EXPR. */
SET_DECL_IMPLICIT_INSTANTIATION (decl);
- gcc_assert (identifier_p (fns)
- || TREE_CODE (fns) == OVERLOAD
- || TREE_CODE (fns) == FUNCTION_DECL);
+ gcc_assert (identifier_p (fns) || OVL_P (fns));
DECL_TEMPLATE_INFO (decl) = build_template_info (fns, args);
for (t = TYPE_ARG_TYPES (TREE_TYPE (decl)); t; t = TREE_CHAIN (t))
{
permerror (DECL_SOURCE_LOCATION (decl),
"friend declaration of %qD specifies default "
- "arguments and isn't a definition", decl);
+ "arguments and isn%'t a definition", decl);
break;
}
}
else if (long_double_p)
{
if (cpp_interpret_float_suffix (parse_in, suffix, strlen (suffix)))
- warning_at (location, 0, "floating point suffix %qs"
+ warning_at (location, 0, "floating-point suffix %qs"
" shadowed by implementation", suffix);
}
/* 17.6.3.3.5 */
int inlinep,
bool conceptp,
int template_count,
- tree scope)
+ tree scope,
+ location_t location)
{
tree decl;
tree explicit_scope;
/* Similarly for explicit specializations. */
|| (orig_declarator
&& TREE_CODE (orig_declarator) == TEMPLATE_ID_EXPR)))
- decl = build_lang_decl (VAR_DECL, name, type);
+ decl = build_lang_decl_loc (location, VAR_DECL, name, type);
else
- decl = build_decl (input_location, VAR_DECL, name, type);
+ decl = build_decl (location, VAR_DECL, name, type);
if (explicit_scope && TREE_CODE (explicit_scope) == NAMESPACE_DECL)
set_decl_namespace (decl, explicit_scope, 0);
if (DECL_NAME (decl)
&& MAIN_NAME_P (DECL_NAME (decl))
&& scope == global_namespace)
- error ("cannot declare %<::main%> to be a global variable");
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "cannot declare %<::main%> to be a global variable");
/* Check that the variable can be safely declared as a concept.
Note that this also forbids explicit specializations. */
compute_array_index_type_loc (location_t name_loc, tree name, tree size,
tsubst_flags_t complain)
{
- tree itype;
- tree osize = size;
-
if (error_operand_p (size))
return error_mark_node;
+ /* The type of the index being computed. */
+ tree itype;
+
+ /* The original numeric size as seen in the source code before
+ conversion to size_t. */
+ tree origsize = size;
+
location_t loc = cp_expr_loc_or_loc (size, name ? name_loc : input_location);
if (!type_dependent_expression_p (size))
{
- osize = size = mark_rvalue_use (size);
+ origsize = size = mark_rvalue_use (size);
if (cxx_dialect < cxx11 && TREE_CODE (size) == NOP_EXPR
&& TREE_SIDE_EFFECTS (size))
{
size = instantiate_non_dependent_expr_sfinae (size, complain);
size = build_converted_constant_expr (size_type_node, size, complain);
- size = maybe_constant_value (size);
+ /* Pedantically a constant expression is required here and so
+ __builtin_is_constant_evaluated () should fold to true if it
+ is successfully folded into a constant. */
+ size = maybe_constant_value (size, NULL_TREE,
+ /*manifestly_const_eval=*/true);
if (!TREE_CONSTANT (size))
- size = osize;
+ size = origsize;
}
if (error_operand_p (size))
/* Normally, the array-bound will be a constant. */
if (TREE_CODE (size) == INTEGER_CST)
{
- /* An array must have a positive number of elements. */
- if (!valid_constant_size_p (size))
+ /* The size to use in diagnostics that reflects the constant
+ size used in the source, rather than SIZE massaged above. */
+ tree diagsize = size;
+
+ /* If the original size before conversion to size_t was signed
+ and negative, convert it to ssizetype to restore the sign. */
+ if (!TYPE_UNSIGNED (TREE_TYPE (origsize))
+ && TREE_CODE (size) == INTEGER_CST
+ && tree_int_cst_sign_bit (size))
+ {
+ diagsize = fold_convert (ssizetype, size);
+
+ /* Clear the overflow bit that may have been set as a result
+ of the conversion from the sizetype of the new size to
+ ssizetype. */
+ TREE_OVERFLOW (diagsize) = false;
+ }
+
+ /* Verify that the array has a positive number of elements
+ and issue the appropriate diagnostic if it doesn't. */
+ if (!valid_array_size_p (loc, diagsize, name, (complain & tf_error)))
{
if (!(complain & tf_error))
return error_mark_node;
-
- if (name)
- error_at (loc, "size of array %qD is negative", name);
- else
- error_at (loc, "size of array is negative");
size = integer_one_node;
}
/* As an extension we allow zero-sized arrays. */
return loc;
}
+/* Returns the smallest among the latter and locations[ds_type_spec]. */
+
+static location_t
+smallest_type_location (int type_quals, const location_t* locations)
+{
+ location_t loc = smallest_type_quals_location (type_quals, locations);
+ return min_location (loc, locations[ds_type_spec]);
+}
+
/* Check that it's OK to declare a function with the indicated TYPE
and TYPE_QUALS. SFK indicates the kind of special function (if any)
that this function is. OPTYPE is the type given in a conversion
{
case sfk_constructor:
if (type)
- error ("return type specification for constructor invalid");
+ error_at (smallest_type_location (type_quals, locations),
+ "return type specification for constructor invalid");
else if (type_quals != TYPE_UNQUALIFIED)
error_at (smallest_type_quals_location (type_quals, locations),
"qualifiers are not allowed on constructor declaration");
case sfk_destructor:
if (type)
- error ("return type specification for destructor invalid");
+ error_at (smallest_type_location (type_quals, locations),
+ "return type specification for destructor invalid");
else if (type_quals != TYPE_UNQUALIFIED)
error_at (smallest_type_quals_location (type_quals, locations),
"qualifiers are not allowed on destructor declaration");
case sfk_conversion:
if (type)
- error ("return type specified for %<operator %T%>", optype);
+ error_at (smallest_type_location (type_quals, locations),
+ "return type specified for %<operator %T%>", optype);
else if (type_quals != TYPE_UNQUALIFIED)
error_at (smallest_type_quals_location (type_quals, locations),
"qualifiers are not allowed on declaration of "
case sfk_deduction_guide:
if (type)
- error ("return type specified for deduction guide");
+ error_at (smallest_type_location (type_quals, locations),
+ "return type specified for deduction guide");
else if (type_quals != TYPE_UNQUALIFIED)
error_at (smallest_type_quals_location (type_quals, locations),
"qualifiers are not allowed on declaration of "
for (int i = 0; i < ds_last; ++i)
if (i != ds_explicit && locations[i])
error_at (locations[i],
- "decl-specifier in declaration of deduction guide");
+ "%<decl-specifier%> in declaration of deduction guide");
break;
default:
}
else if (cxx_dialect < cxx17)
pedwarn (loc, 0, "inline variables are only available "
- "with -std=c++17 or -std=gnu++17");
+ "with %<-std=c++17%> or %<-std=gnu++17%>");
if (inlinep)
{
retrofit_lang_decl (decl);
/* Replace the anonymous name with the real name everywhere. */
for (tree t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
- {
- if (anon_aggrname_p (TYPE_IDENTIFIER (t)))
- /* We do not rename the debug info representing the
- unnamed 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 (IDENTIFIER_ANON_P (TYPE_IDENTIFIER (t)))
+ /* We do not rename the debug info representing the unnamed
+ 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))
TYPE_WAS_UNNAMED (type) = 1;
if (initialized > 1)
funcdef_flag = true;
- location_t typespec_loc = smallest_type_quals_location (type_quals,
- declspecs->locations);
- if (typespec_loc == UNKNOWN_LOCATION)
- typespec_loc = declspecs->locations[ds_type_spec];
+ location_t typespec_loc = smallest_type_location (type_quals,
+ declspecs->locations);
if (typespec_loc == UNKNOWN_LOCATION)
typespec_loc = input_location;
+ location_t id_loc = declarator ? declarator->id_loc : input_location;
+ if (id_loc == UNKNOWN_LOCATION)
+ id_loc = input_location;
+
/* Look inside a declarator for the name being declared
and get it as a string, for an error message. */
for (id_declarator = declarator;
D1 ( parameter-declaration-clause) ... */
if (funcdef_flag && innermost_code != cdk_function)
{
- error ("function definition does not declare parameters");
+ error_at (id_loc, "function definition does not declare parameters");
return error_mark_node;
}
&& innermost_code != cdk_function
&& ! (ctype && !declspecs->any_specifiers_p))
{
- error ("declaration of %qD as non-function", dname);
+ error_at (id_loc, "declaration of %qD as non-function", dname);
return error_mark_node;
}
if (UDLIT_OPER_P (dname)
&& innermost_code != cdk_function)
{
- error ("declaration of %qD as non-function", dname);
+ error_at (id_loc, "declaration of %qD as non-function", dname);
return error_mark_node;
}
{
if (typedef_p)
{
- error ("declaration of %qD as %<typedef%>", dname);
+ error_at (id_loc, "declaration of %qD as %<typedef%>", dname);
return error_mark_node;
}
else if (decl_context == PARM || decl_context == CATCHPARM)
{
- error ("declaration of %qD as parameter", dname);
+ error_at (id_loc, "declaration of %qD as parameter", dname);
return error_mark_node;
}
}
issue an error message. */
if (declspecs->multiple_types_p)
{
- error ("two or more data types in declaration of %qs", name);
+ error_at (typespec_loc,
+ "two or more data types in declaration of %qs", name);
return error_mark_node;
}
if (declspecs->conflicting_specifiers_p)
{
- error ("conflicting specifiers in declaration of %qs", name);
+ error_at (min_location (declspecs->locations[ds_typedef],
+ declspecs->locations[ds_storage_class]),
+ "conflicting specifiers in declaration of %qs", name);
return error_mark_node;
}
error_at (&richloc, "%<long%> and %<short%> specified together");
}
else if (TREE_CODE (type) != INTEGER_TYPE
- || type == char16_type_node || type == char32_type_node
+ || type == char8_type_node
+ || type == char16_type_node
+ || type == char32_type_node
|| ((long_p || short_p)
&& (explicit_char || explicit_intN)))
error_at (loc, "%qs specified with %qT", key, type);
error_at (typespec_loc, "template placeholder type %qT must be followed "
"by a simple declarator-id", type);
inform (DECL_SOURCE_LOCATION (tmpl), "%qD declared here", tmpl);
+ type = error_mark_node;
}
staticp = 0;
gcc_rich_location richloc (declspecs->locations[ds_virtual]);
richloc.add_range (declspecs->locations[ds_constexpr]);
pedwarn (&richloc, OPT_Wpedantic, "member %qD can be declared both "
- "%<virtual%> and %<constexpr%> only in -std=c++2a or "
- "-std=gnu++2a", dname);
+ "%<virtual%> and %<constexpr%> only in %<-std=c++2a%> or "
+ "%<-std=gnu++2a%>", dname);
}
}
friendp = decl_spec_seq_has_spec_p (declspecs, ds_friend);
? declarator->declarator->id_loc : declarator->id_loc);
if (inlinep)
error_at (declspecs->locations[ds_inline],
- "structured binding declaration cannot be %<inline%>");
+ "structured binding declaration cannot be %qs", "inline");
if (typedef_p)
error_at (declspecs->locations[ds_typedef],
- "structured binding declaration cannot be %<typedef%>");
+ "structured binding declaration cannot be %qs", "typedef");
if (constexpr_p)
error_at (declspecs->locations[ds_constexpr], "structured "
- "binding declaration cannot be %<constexpr%>");
- if (thread_p)
- error_at (declspecs->locations[ds_thread],
- "structured binding declaration cannot be %qs",
- declspecs->gnu_thread_keyword_p
- ? "__thread" : "thread_local");
+ "binding declaration cannot be %qs", "constexpr");
+ if (thread_p && cxx_dialect < cxx2a)
+ pedwarn (declspecs->locations[ds_thread], 0,
+ "structured binding declaration can be %qs only in "
+ "%<-std=c++2a%> or %<-std=gnu++2a%>",
+ declspecs->gnu_thread_keyword_p
+ ? "__thread" : "thread_local");
if (concept_p)
error_at (declspecs->locations[ds_concept],
- "structured binding declaration cannot be %<concept%>");
+ "structured binding declaration cannot be %qs", "concept");
switch (storage_class)
{
case sc_none:
break;
case sc_register:
- error_at (loc, "structured binding declaration cannot be "
- "%<register%>");
+ error_at (loc, "structured binding declaration cannot be %qs",
+ "register");
break;
case sc_static:
- error_at (loc, "structured binding declaration cannot be "
- "%<static%>");
+ if (cxx_dialect < cxx2a)
+ pedwarn (loc, 0,
+ "structured binding declaration can be %qs only in "
+ "%<-std=c++2a%> or %<-std=gnu++2a%>", "static");
break;
case sc_extern:
- error_at (loc, "structured binding declaration cannot be "
- "%<extern%>");
+ error_at (loc, "structured binding declaration cannot be %qs",
+ "extern");
break;
case sc_mutable:
- error_at (loc, "structured binding declaration cannot be "
- "%<mutable%>");
+ error_at (loc, "structured binding declaration cannot be %qs",
+ "mutable");
break;
case sc_auto:
error_at (loc, "structured binding declaration cannot be "
inlinep = 0;
typedef_p = 0;
constexpr_p = 0;
- thread_p = 0;
concept_p = 0;
- storage_class = sc_none;
- staticp = 0;
- declspecs->storage_class = sc_none;
- declspecs->locations[ds_thread] = UNKNOWN_LOCATION;
+ if (storage_class != sc_static)
+ {
+ storage_class = sc_none;
+ declspecs->storage_class = sc_none;
+ }
}
/* Static anonymous unions are dealt with here. */
/* OK for C++11 lambdas. */;
else if (cxx_dialect < cxx14)
{
- error ("%qs function uses "
- "%<auto%> type specifier without trailing "
- "return type", name);
- inform (input_location, "deduced return type "
- "only available with -std=c++14 or "
- "-std=gnu++14");
+ error_at (typespec_loc, "%qs function uses "
+ "%<auto%> type specifier without "
+ "trailing return type", name);
+ inform (typespec_loc,
+ "deduced return type only available "
+ "with %<-std=c++14%> or %<-std=gnu++14%>");
}
else if (virtualp)
{
- error ("virtual function cannot "
- "have deduced return type");
+ error_at (typespec_loc, "virtual function "
+ "cannot have deduced return type");
virtualp = false;
}
}
else if (!is_auto (type) && sfk != sfk_conversion)
{
- error ("%qs function with trailing return type has"
- " %qT as its type rather than plain %<auto%>",
- name, type);
+ error_at (typespec_loc, "%qs function with trailing "
+ "return type has %qT as its type rather "
+ "than plain %<auto%>", name, type);
return error_mark_node;
}
else if (is_auto (type) && AUTO_IS_DECLTYPE (type))
{
if (funcdecl_p)
- error ("%qs function with trailing return type has "
- "%<decltype(auto)%> as its type rather than "
- "plain %<auto%>", name);
+ error_at (typespec_loc,
+ "%qs function with trailing return type "
+ "has %<decltype(auto)%> as its type "
+ "rather than plain %<auto%>", name);
else
- error ("invalid use of %<decltype(auto)%>");
+ error_at (typespec_loc,
+ "invalid use of %<decltype(auto)%>");
return error_mark_node;
}
tree tmpl = CLASS_PLACEHOLDER_TEMPLATE (auto_node);
if (cxx_dialect < cxx11)
/* Not using maybe_warn_cpp0x because this should
always be an error. */
- error ("trailing return type only available with "
- "-std=c++11 or -std=gnu++11");
+ error_at (typespec_loc,
+ "trailing return type only available "
+ "with %<-std=c++11%> or %<-std=gnu++11%>");
else
- error ("%qs function with trailing return type not "
- "declared with %<auto%> type specifier", name);
+ error_at (typespec_loc, "%qs function with trailing "
+ "return type not declared with %<auto%> "
+ "type specifier", name);
return error_mark_node;
}
}
error ("friend declaration not in class definition");
if (current_function_decl && funcdef_flag)
{
- error ("can%'t define friend function %qs in a local "
+ error ("cannot define friend function %qs in a local "
"class definition", name);
friendp = 0;
}
}
}
+ id_loc = declarator ? declarator->id_loc : input_location;
+
/* A `constexpr' specifier used in an object declaration declares
the object as `const'. */
if (constexpr_p && innermost_code != cdk_function)
}
if (unqualified_id && TREE_CODE (unqualified_id) == TEMPLATE_ID_EXPR
- && TREE_CODE (type) != FUNCTION_TYPE
- && TREE_CODE (type) != METHOD_TYPE
+ && !FUNC_OR_METHOD_TYPE_P (type)
&& !variable_template_p (TREE_OPERAND (unqualified_id, 0)))
{
error ("template-id %qD used as a declarator",
{
if (friendp)
{
- permerror (input_location, "member functions are implicitly "
- "friends of their class");
+ permerror (declspecs->locations[ds_friend],
+ "member functions are implicitly "
+ "friends of their class");
friendp = 0;
}
else
- permerror (declarator->id_loc,
- "extra qualification %<%T::%> on member %qs",
+ permerror (id_loc, "extra qualification %<%T::%> on member %qs",
ctype, name);
}
else if (/* If the qualifying type is already complete, then we
if (current_class_type
&& (!friendp || funcdef_flag || initialized))
{
- error (funcdef_flag || initialized
- ? G_("cannot define member function %<%T::%s%> "
- "within %qT")
- : G_("cannot declare member function %<%T::%s%> "
- "within %qT"),
- ctype, name, current_class_type);
+ error_at (id_loc, funcdef_flag || initialized
+ ? G_("cannot define member function %<%T::%s%> "
+ "within %qT")
+ : G_("cannot declare member function %<%T::%s%> "
+ "within %qT"),
+ ctype, name, current_class_type);
return error_mark_node;
}
}
else if (typedef_p && current_class_type)
{
- error ("cannot declare member %<%T::%s%> within %qT",
- ctype, name, current_class_type);
+ error_at (id_loc, "cannot declare member %<%T::%s%> within %qT",
+ ctype, name, current_class_type);
return error_mark_node;
}
}
&& variably_modified_type_p (type, NULL_TREE))
{
if (decl_context == FIELD)
- error ("data member may not have variably modified type %qT", type);
+ error_at (id_loc,
+ "data member may not have variably modified type %qT", type);
else
- error ("parameter may not have variably modified type %qT", type);
+ error_at (id_loc,
+ "parameter may not have variably modified type %qT", type);
type = error_mark_node;
}
if (storage_class == sc_mutable)
{
+ location_t sloc = declspecs->locations[ds_storage_class];
if (decl_context != FIELD || friendp)
{
- error ("non-member %qs cannot be declared %<mutable%>", name);
+ error_at (sloc, "non-member %qs cannot be declared %<mutable%>",
+ name);
storage_class = sc_none;
}
else if (decl_context == TYPENAME || typedef_p)
{
- error ("non-object member %qs cannot be declared %<mutable%>", name);
+ error_at (sloc,
+ "non-object member %qs cannot be declared %<mutable%>",
+ name);
storage_class = sc_none;
}
- else if (TREE_CODE (type) == FUNCTION_TYPE
- || TREE_CODE (type) == METHOD_TYPE)
+ else if (FUNC_OR_METHOD_TYPE_P (type))
{
- error ("function %qs cannot be declared %<mutable%>", name);
+ error_at (sloc, "function %qs cannot be declared %<mutable%>",
+ name);
storage_class = sc_none;
}
else if (staticp)
{
- error ("static %qs cannot be declared %<mutable%>", name);
+ error_at (sloc, "%<static%> %qs cannot be declared %<mutable%>",
+ name);
storage_class = sc_none;
}
else if (type_quals & TYPE_QUAL_CONST)
{
- error ("const %qs cannot be declared %<mutable%>", name);
+ error_at (sloc, "%<const%> %qs cannot be declared %<mutable%>",
+ name);
storage_class = sc_none;
}
else if (TYPE_REF_P (type))
{
- permerror (input_location, "reference %qs cannot be declared "
- "%<mutable%>", name);
+ permerror (sloc, "reference %qs cannot be declared %<mutable%>",
+ name);
storage_class = sc_none;
}
}
if (id_declarator && declarator->u.id.qualifying_scope)
{
- error ("typedef name may not be a nested-name-specifier");
+ error_at (id_loc, "typedef name may not be a nested-name-specifier");
type = error_mark_node;
}
if (decl_context == FIELD)
- decl = build_lang_decl (TYPE_DECL, unqualified_id, type);
+ decl = build_lang_decl_loc (id_loc, TYPE_DECL, unqualified_id, type);
else
- decl = build_decl (input_location, TYPE_DECL, unqualified_id, type);
+ decl = build_decl (id_loc, TYPE_DECL, unqualified_id, type);
if (decl_context != FIELD)
{
}
else if (current_class_type
&& constructor_name_p (unqualified_id, current_class_type))
- permerror (input_location, "ISO C++ forbids nested type %qD with same name "
+ permerror (id_loc, "ISO C++ forbids nested type %qD with same name "
"as enclosing class",
unqualified_id);
/* Only functions may be declared using an operator-function-id. */
if (dname && IDENTIFIER_ANY_OP_P (dname))
{
- error ("declaration of %qD as non-function", dname);
+ error_at (id_loc, "declaration of %qD as non-function", dname);
return error_mark_node;
}
}
if (ctype && TREE_CODE (type) == FUNCTION_TYPE && staticp < 2
- && !(identifier_p (unqualified_id)
+ && !(unqualified_id
+ && identifier_p (unqualified_id)
&& IDENTIFIER_NEWDEL_OP_P (unqualified_id)))
{
cp_cv_quals real_quals = memfn_quals;
if (!staticp && !friendp && TREE_CODE (type) != METHOD_TYPE)
if (tree auto_node = type_uses_auto (type))
{
- location_t loc = declspecs->locations[ds_type_spec];
+ location_t tloc = declspecs->locations[ds_type_spec];
if (CLASS_PLACEHOLDER_TEMPLATE (auto_node))
- error_at (loc, "invalid use of template-name %qE without an "
+ error_at (tloc, "invalid use of template-name %qE without an "
"argument list",
CLASS_PLACEHOLDER_TEMPLATE (auto_node));
else
- error_at (loc, "non-static data member declared with "
+ error_at (tloc, "non-static data member declared with "
"placeholder %qT", auto_node);
type = error_mark_node;
}
if (in_system_header_at (input_location))
/* Do not warn on flexible array members in system
headers because glibc uses them. */;
- else if (name && declarator)
- pedwarn (declarator->id_loc, OPT_Wpedantic,
+ else if (name)
+ pedwarn (id_loc, OPT_Wpedantic,
"ISO C++ forbids flexible array member %qs", name);
else
pedwarn (input_location, OPT_Wpedantic,
error ("invalid use of %<::%>");
return error_mark_node;
}
- else if (TREE_CODE (type) == FUNCTION_TYPE
- || TREE_CODE (type) == METHOD_TYPE)
+ else if (FUNC_OR_METHOD_TYPE_P (type) && unqualified_id)
{
int publicp = 0;
tree function_context;
initialized == SD_DELETED, sfk,
funcdef_flag, late_return_type_p,
template_count, in_namespace,
- attrlist, declarator->id_loc);
+ attrlist, id_loc);
decl = set_virt_specifiers (decl, virt_specifiers);
if (decl == NULL_TREE)
return error_mark_node;
{
if (unqualified_id)
{
- error_at (declarator->id_loc,
- "field %qD has incomplete type %qT",
+ error_at (id_loc, "field %qD has incomplete type %qT",
unqualified_id, type);
cxx_incomplete_type_inform (strip_array_types (type));
}
{
if (friendp)
{
- error_at (declarator->id_loc,
- "%qE is neither function nor member function; "
- "cannot be declared friend", unqualified_id);
+ if (unqualified_id)
+ error_at (id_loc,
+ "%qE is neither function nor member function; "
+ "cannot be declared friend", unqualified_id);
+ else
+ error ("unnamed field is neither function nor member "
+ "function; cannot be declared friend");
return error_mark_node;
}
decl = NULL_TREE;
{
/* C++ allows static class members. All other work
for this is done by grokfield. */
- decl = build_lang_decl_loc (declarator
- ? declarator->id_loc
- : input_location,
- VAR_DECL, unqualified_id, type);
+ decl = build_lang_decl_loc (id_loc, VAR_DECL,
+ unqualified_id, type);
set_linkage_for_static_data_member (decl);
if (concept_p)
error_at (declspecs->locations[ds_concept],
unqualified_id);
else if (constexpr_p && !initialized)
{
- error ("%<constexpr%> static data member %qD must have an "
- "initializer", decl);
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "%<constexpr%> static data member %qD must "
+ "have an initializer", decl);
constexpr_p = false;
}
unqualified_id);
constexpr_p = false;
}
- decl = build_decl (input_location,
- FIELD_DECL, unqualified_id, type);
+ decl = build_decl (id_loc, FIELD_DECL, unqualified_id, type);
DECL_NONADDRESSABLE_P (decl) = bitfield;
if (bitfield && !unqualified_id)
{
declspecs->locations);
}
}
- else if (TREE_CODE (type) == FUNCTION_TYPE
- || TREE_CODE (type) == METHOD_TYPE)
+ else if (FUNC_OR_METHOD_TYPE_P (type))
{
tree original_name;
int publicp = 0;
funcdef_flag,
late_return_type_p,
template_count, in_namespace, attrlist,
- declarator->id_loc);
+ id_loc);
if (decl == NULL_TREE)
return error_mark_node;
inlinep,
concept_p,
template_count,
- ctype ? ctype : in_namespace);
+ ctype ? ctype : in_namespace,
+ id_loc);
if (decl == NULL_TREE)
return error_mark_node;
DECL_CONTEXT (decl) = ctype;
if (staticp == 1)
{
- permerror (input_location, "%<static%> may not be used when defining "
+ permerror (declspecs->locations[ds_storage_class],
+ "%<static%> may not be used when defining "
"(as opposed to declaring) a static data member");
staticp = 0;
storage_class = sc_none;
}
else if (constexpr_p && DECL_EXTERNAL (decl))
{
- error ("declaration of %<constexpr%> variable %qD "
- "is not a definition", decl);
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "declaration of %<constexpr%> variable %qD "
+ "is not a definition", decl);
constexpr_p = false;
}
if (innermost_code == cdk_decomp)
{
gcc_assert (declarator && declarator->kind == cdk_decomp);
- DECL_SOURCE_LOCATION (decl) = declarator->id_loc;
+ DECL_SOURCE_LOCATION (decl) = id_loc;
DECL_ARTIFICIAL (decl) = 1;
fit_decomposition_lang_decl (decl, NULL_TREE);
}
/* It's common practice (and completely valid) to have a const
be initialized and declared extern. */
if (!(type_quals & TYPE_QUAL_CONST))
- warning (0, "%qs initialized and declared %<extern%>", name);
+ warning_at (DECL_SOURCE_LOCATION (decl), 0,
+ "%qs initialized and declared %<extern%>", name);
}
else
{
- error ("%qs has both %<extern%> and initializer", name);
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "%qs has both %<extern%> and initializer", name);
return error_mark_node;
}
}
{
tree class_type;
- if (!DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
+ if (TREE_CODE (decl) == USING_DECL
+ || !DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
return;
class_type = DECL_CONTEXT (decl);
if (operator_code == COND_EXPR)
{
/* 13.4.0.3 */
- error_at (loc, "ISO C++ prohibits overloading operator ?:");
+ error_at (loc, "ISO C++ prohibits overloading %<operator ?:%>");
return false;
}
/* In case of anonymous name, xref_tag is only called to
make type node and push name. Name lookup is not required. */
tree t = NULL_TREE;
- if (scope != ts_lambda && !anon_aggrname_p (name))
+ if (scope != ts_lambda && !IDENTIFIER_ANON_P (name))
t = lookup_and_check_tag (tag_code, name, scope, template_header_p);
if (t == error_mark_node)
if (TYPE_PRECISION (enumtype))
{
if (precision > TYPE_PRECISION (enumtype))
- error ("specified mode too small for enumeral values");
+ error ("specified mode too small for enumerated values");
else
{
use_short_enum = true;
if (DECL_DECLARED_INLINE_P (decl1)
&& lookup_attribute ("noinline", attrs))
warning_at (DECL_SOURCE_LOCATION (decl1), 0,
- "inline function %qD given attribute noinline", decl1);
+ "inline function %qD given attribute %qs", decl1, "noinline");
/* Handle gnu_inline attribute. */
if (GNU_INLINE_P (decl1))
current_stmt_tree ()->stmts_are_full_exprs_p = 1;
current_binding_level = bl;
+ /* If we are (erroneously) defining a function that we have already
+ defined before, wipe out what we knew before. */
+ gcc_checking_assert (!DECL_PENDING_INLINE_P (decl1));
+ FNDECL_USED_AUTO (decl1) = false;
+ DECL_SAVED_AUTO_RETURN_TYPE (decl1) = NULL;
+
if (!processing_template_decl && type_uses_auto (restype))
{
FNDECL_USED_AUTO (decl1) = true;
- current_function_auto_return_pattern = restype;
+ DECL_SAVED_AUTO_RETURN_TYPE (decl1) = restype;
}
/* Start the statement-tree, start the tree now. */
DECL_SAVED_TREE (decl1) = push_stmt_list ();
- /* If we are (erroneously) defining a function that we have already
- defined before, wipe out what we knew before. */
- if (!DECL_PENDING_INLINE_P (decl1))
- DECL_SAVED_FUNCTION_DATA (decl1) = NULL;
-
if (ctype && !doing_friend && !DECL_STATIC_FUNCTION_P (decl1))
{
/* We know that this was set up by `grokclassfn'. We do not
store_parm_decls (current_function_parms);
+ push_operator_bindings ();
+
if (!processing_template_decl
&& (flag_lifetime_dse > 1)
&& DECL_CONSTRUCTOR_P (decl1)
}
\f
-/* We have finished doing semantic analysis on DECL, but have not yet
- generated RTL for its body. Save away our current state, so that
- when we want to generate RTL later we know what to do. */
-
-static void
-save_function_data (tree decl)
-{
- struct language_function *f;
-
- /* Save the language-specific per-function data so that we can
- get it back when we really expand this function. */
- gcc_assert (!DECL_PENDING_INLINE_P (decl));
-
- /* Make a copy. */
- f = ggc_alloc<language_function> ();
- memcpy (f, cp_function_chain, sizeof (struct language_function));
- DECL_SAVED_FUNCTION_DATA (decl) = f;
-
- /* Clear out the bits we don't need. */
- f->base.x_stmt_tree.x_cur_stmt_list = NULL;
- f->bindings = NULL;
- f->base.local_typedefs = NULL;
-}
-
-
/* Set the return value of the constructor (if present). */
static void
the return type is void. But if the declared type is something like
auto*, this is an error. */
if (!processing_template_decl && FNDECL_USED_AUTO (fndecl)
- && TREE_TYPE (fntype) == current_function_auto_return_pattern)
+ && TREE_TYPE (fntype) == DECL_SAVED_AUTO_RETURN_TYPE (fndecl))
{
- if (is_auto (current_function_auto_return_pattern))
+ if (is_auto (DECL_SAVED_AUTO_RETURN_TYPE (fndecl)))
{
apply_deduced_return_type (fndecl, void_type_node);
fntype = TREE_TYPE (fndecl);
&& !current_function_returns_null)
{
error ("no return statements in function returning %qT",
- current_function_auto_return_pattern);
+ DECL_SAVED_AUTO_RETURN_TYPE (fndecl));
inform (input_location, "only plain %<auto%> return type can be "
"deduced to %<void%>");
}
to the FUNCTION_DECL node itself. */
BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
- /* Save away current state, if appropriate. */
- if (!processing_template_decl)
- save_function_data (fndecl);
-
/* Complain if there's just no return statement. */
if (warn_return_type
&& !VOID_TYPE_P (TREE_TYPE (fntype))
{
tree valtype = TREE_TYPE (DECL_RESULT (fndecl));
if (TREE_CODE (valtype) == REFERENCE_TYPE
+ && current_class_ref
&& same_type_ignoring_top_level_qualifiers_p
- (TREE_TYPE (valtype), TREE_TYPE (current_class_ref)))
- if (global_dc->option_enabled (OPT_Wreturn_type,
- global_dc->option_state))
- add_return_star_this_fixit (&richloc, fndecl);
+ (TREE_TYPE (valtype), TREE_TYPE (current_class_ref))
+ && global_dc->option_enabled (OPT_Wreturn_type,
+ global_dc->option_state))
+ add_return_star_this_fixit (&richloc, fndecl);
}
- warning_at (&richloc, OPT_Wreturn_type,
- "no return statement in function returning non-void");
- TREE_NO_WARNING (fndecl) = 1;
+ if (warning_at (&richloc, OPT_Wreturn_type,
+ "no return statement in function returning non-void"))
+ TREE_NO_WARNING (fndecl) = 1;
}
/* Store the end of the function, so that we get good line number
/* Genericize before inlining. */
if (!processing_template_decl)
- {
- struct language_function *f = DECL_SAVED_FUNCTION_DATA (fndecl);
- cp_genericize (fndecl);
- /* Clear out the bits we don't need. */
- f->x_current_class_ptr = NULL;
- f->x_current_class_ref = NULL;
- f->x_eh_spec_block = NULL;
- f->x_in_charge_parm = NULL;
- f->x_vtt_parm = NULL;
- f->x_return_value = NULL;
- f->bindings = NULL;
- f->extern_decl_map = NULL;
- f->infinite_loops = NULL;
- }
+ cp_genericize (fndecl);
/* We're leaving the context of this function, so zap cfun. It's still in
DECL_STRUCT_FUNCTION, and we'll restore it in tree_rest_of_compilation. */
{
fn = STRIP_TEMPLATE (fn);
if (FNDECL_USED_AUTO (fn))
- {
- struct language_function *f = NULL;
- if (DECL_STRUCT_FUNCTION (fn))
- f = DECL_STRUCT_FUNCTION (fn)->language;
- if (f == NULL)
- f = DECL_SAVED_FUNCTION_DATA (fn);
- return f->x_auto_return_pattern;
- }
+ return DECL_SAVED_AUTO_RETURN_TYPE (fn);
+
return TREE_TYPE (TREE_TYPE (fn));
}
{
if (cxx_dialect < cxx11)
return false;
+ STRIP_ANY_LOCATION_WRAPPER (decl);
return ((VAR_OR_FUNCTION_DECL_P (decl)
|| TREE_CODE (decl) == TEMPLATE_DECL)
&& type_uses_auto (TREE_TYPE (decl)));
tree
build_explicit_specifier (tree expr, tsubst_flags_t complain)
{
- if (processing_template_decl && value_dependent_expression_p (expr))
+ if (instantiation_dependent_expression_p (expr))
/* Wait for instantiation, tsubst_function_decl will handle it. */
return expr;
- expr = build_converted_constant_expr (boolean_type_node, expr, complain);
- expr = instantiate_non_dependent_expr (expr);
+ expr = instantiate_non_dependent_expr_sfinae (expr, complain);
+ /* Don't let convert_like_real create more template codes. */
+ processing_template_decl_sentinel s;
+ expr = build_converted_constant_bool_expr (expr, complain);
expr = cxx_constant_value (expr);
return expr;
}