static void store_parm_decls (tree);
static void initialize_local_var (tree, tree);
static void expand_static_init (tree, tree);
+static location_t smallest_type_location (const cp_decl_specifier_seq*);
/* The following symbols are subsumed in the cp_global_trees array, and
listed here individually for documentation purposes.
}
\f
+
+/* Returns true if functions FN1 and FN2 have equivalent trailing
+ requires clauses. */
+
+static bool
+function_requirements_equivalent_p (tree newfn, tree oldfn)
+{
+ /* In the concepts TS, the combined constraints are compared. */
+ if (cxx_dialect < cxx2a)
+ {
+ tree ci1 = get_constraints (oldfn);
+ tree ci2 = get_constraints (newfn);
+ tree req1 = ci1 ? CI_ASSOCIATED_CONSTRAINTS (ci1) : NULL_TREE;
+ tree req2 = ci2 ? CI_ASSOCIATED_CONSTRAINTS (ci2) : NULL_TREE;
+ return cp_tree_equal (req1, req2);
+ }
+
+ /* Compare only trailing requirements. */
+ tree reqs1 = get_trailing_function_requirements (newfn);
+ tree reqs2 = get_trailing_function_requirements (oldfn);
+ if ((reqs1 != NULL_TREE) != (reqs2 != NULL_TREE))
+ return false;
+ return cp_tree_equal (reqs1, reqs2);
+}
+
/* Subroutine of duplicate_decls: return truthvalue of whether
or not types of these decls match.
else
types_match = 0;
+ /* Two function declarations match if either has a requires-clause
+ then both have a requires-clause and their constraints-expressions
+ are equivalent. */
+ if (types_match && flag_concepts)
+ types_match = function_requirements_equivalent_p (newdecl, olddecl);
+
/* The decls dont match if they correspond to two different versions
of the same function. Disallow extern "C" functions to be
versions for now. */
}
else if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
+ if (!template_heads_equivalent_p (newdecl, olddecl))
+ return 0;
+
tree oldres = DECL_TEMPLATE_RESULT (olddecl);
tree newres = DECL_TEMPLATE_RESULT (newdecl);
if (TREE_CODE (newres) != TREE_CODE (oldres))
return 0;
- if (!comp_template_parms (DECL_TEMPLATE_PARMS (newdecl),
- DECL_TEMPLATE_PARMS (olddecl)))
- return 0;
-
- if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)
- types_match = (same_type_p (TREE_TYPE (oldres), TREE_TYPE (newres))
- && equivalently_constrained (olddecl, newdecl));
+ /* Two template types match if they are the same. Otherwise, compare
+ the underlying declarations. */
+ if (TREE_CODE (newres) == TYPE_DECL)
+ types_match = same_type_p (TREE_TYPE (newres), TREE_TYPE (oldres));
else
- // We don't need to check equivalently_constrained for variable and
- // function templates because we check it on the results.
- types_match = decls_match (oldres, newres);
+ types_match = decls_match (newres, oldres);
}
else
{
COMPARE_REDECLARATION);
}
- // Normal functions can be constrained, as can variable partial
- // specializations.
- if (types_match && VAR_OR_FUNCTION_DECL_P (newdecl))
- types_match = equivalently_constrained (newdecl, olddecl);
-
return types_match;
}
&& lookup_attribute ("gnu_inline", \
DECL_ATTRIBUTES (fn)))
+/* A subroutine of duplicate_decls. Emits a diagnostic when newdecl
+ ambiguates olddecl. Returns true if an error occurs. */
+
+static bool
+duplicate_function_template_decls (tree newdecl, tree olddecl)
+{
+
+ tree newres = DECL_TEMPLATE_RESULT (newdecl);
+ tree oldres = DECL_TEMPLATE_RESULT (olddecl);
+ /* Function template declarations can be differentiated by parameter
+ and return type. */
+ if (compparms (TYPE_ARG_TYPES (TREE_TYPE (oldres)),
+ TYPE_ARG_TYPES (TREE_TYPE (newres)))
+ && same_type_p (TREE_TYPE (TREE_TYPE (newdecl)),
+ TREE_TYPE (TREE_TYPE (olddecl))))
+ {
+ /* ... and also by their template-heads and requires-clauses. */
+ if (template_heads_equivalent_p (newdecl, olddecl)
+ && function_requirements_equivalent_p (newres, oldres))
+ {
+ error ("ambiguating new declaration %q+#D", newdecl);
+ inform (DECL_SOURCE_LOCATION (olddecl),
+ "old declaration %q#D", olddecl);
+ return true;
+ }
+
+ /* FIXME: The types are the same but the are differences
+ in either the template heads or function requirements.
+ We should be able to diagnose a set of common errors
+ stemming from these declarations. For example:
+
+ template<typename T> requires C void f(...);
+ template<typename T> void f(...) requires C;
+
+ These are functionally equivalent but not equivalent. */
+ }
+
+ return false;
+}
+
/* If NEWDECL is a redeclaration of OLDDECL, merge the declarations.
If the redeclaration is invalid, a diagnostic is issued, and the
error_mark_node is returned. Otherwise, OLDDECL is returned.
if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
+ tree oldres = DECL_TEMPLATE_RESULT (olddecl);
+ tree newres = DECL_TEMPLATE_RESULT (newdecl);
+
/* The name of a class template may not be declared to refer to
any other template, class, function, object, namespace, value,
or type in the same scope. */
- if (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == TYPE_DECL
- || TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)
+ if (TREE_CODE (oldres) == TYPE_DECL
+ || TREE_CODE (newres) == TYPE_DECL)
{
error_at (newdecl_loc,
"conflicting declaration of template %q#D", newdecl);
"previous declaration %q#D", olddecl);
return error_mark_node;
}
- else if (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == FUNCTION_DECL
- && TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == FUNCTION_DECL
- && compparms (TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl))),
- TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (newdecl))))
- && comp_template_parms (DECL_TEMPLATE_PARMS (newdecl),
- DECL_TEMPLATE_PARMS (olddecl))
- /* Template functions can be disambiguated by
- return type. */
- && same_type_p (TREE_TYPE (TREE_TYPE (newdecl)),
- TREE_TYPE (TREE_TYPE (olddecl)))
- /* Template functions can also be disambiguated by
- constraints. */
- && equivalently_constrained (olddecl, newdecl))
+
+ else if (TREE_CODE (oldres) == FUNCTION_DECL
+ && TREE_CODE (newres) == FUNCTION_DECL)
{
- error_at (newdecl_loc, "ambiguating new declaration %q#D",
- newdecl);
- inform (olddecl_loc,
- "old declaration %q#D", olddecl);
+ if (duplicate_function_template_decls (newdecl, olddecl))
+ return error_mark_node;
+ return NULL_TREE;
}
else if (check_concept_refinement (olddecl, newdecl))
return error_mark_node;
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
- if (merge_attr && diagnose_mismatched_attributes (olddecl, newdecl))
- inform (olddecl_loc, DECL_INITIAL (olddecl)
- ? G_("previous definition of %qD here")
- : G_("previous declaration of %qD here"), olddecl);
+ if (merge_attr)
+ {
+ if (diagnose_mismatched_attributes (olddecl, newdecl))
+ inform (olddecl_loc, DECL_INITIAL (olddecl)
+ ? G_("previous definition of %qD here")
+ : G_("previous declaration of %qD here"), olddecl);
+
+ /* [dcl.attr.noreturn]: The first declaration of a function shall
+ specify the noreturn attribute if any declaration of that function
+ specifies the noreturn attribute. */
+ tree a;
+ if (TREE_THIS_VOLATILE (newdecl)
+ && !TREE_THIS_VOLATILE (olddecl)
+ /* This applies to [[noreturn]] only, not its GNU variants. */
+ && (a = lookup_attribute ("noreturn", DECL_ATTRIBUTES (newdecl)))
+ && cxx11_attribute_p (a)
+ && get_attribute_namespace (a) == NULL_TREE)
+ {
+ error_at (newdecl_loc, "function %qD declared %<[[noreturn]]%> "
+ "but its first declaration was not", newdecl);
+ inform (olddecl_loc, "previous declaration of %qD", olddecl);
+ }
+ }
/* Now that functions must hold information normally held
by field decls, there is extra work to do so that
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);
SET_DECL_DEPENDENT_INIT_P (newdecl, true);
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (newdecl)
|= DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (olddecl);
- if (DECL_CLASS_SCOPE_P (olddecl))
- DECL_DECLARED_CONSTEXPR_P (newdecl)
- |= DECL_DECLARED_CONSTEXPR_P (olddecl);
+ DECL_DECLARED_CONSTEXPR_P (newdecl)
+ |= DECL_DECLARED_CONSTEXPR_P (olddecl);
/* Merge the threadprivate attribute from OLDDECL into NEWDECL. */
if (DECL_LANG_SPECIFIC (olddecl)
DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
|= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
DECL_NO_LIMIT_STACK (newdecl) |= DECL_NO_LIMIT_STACK (olddecl);
- DECL_IS_OPERATOR_NEW (newdecl) |= DECL_IS_OPERATOR_NEW (olddecl);
+ if (DECL_IS_OPERATOR_NEW_P (olddecl))
+ DECL_SET_IS_OPERATOR_NEW (newdecl, true);
DECL_LOOPING_CONST_OR_PURE_P (newdecl)
|= DECL_LOOPING_CONST_OR_PURE_P (olddecl);
/* Don't really know how much of the language-specific
values we should copy from old to new. */
DECL_IN_AGGR_P (newdecl) = DECL_IN_AGGR_P (olddecl);
- DECL_REPO_AVAILABLE_P (newdecl) = DECL_REPO_AVAILABLE_P (olddecl);
DECL_INITIALIZED_IN_CLASS_P (newdecl)
|= DECL_INITIALIZED_IN_CLASS_P (olddecl);
if (fndecl_built_in_p (olddecl)
&& (new_defines_function ? GNU_INLINE_P (newdecl) : types_match))
{
- DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
- DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
+ copy_decl_built_in_function (newdecl, olddecl);
/* If we're keeping the built-in definition, keep the rtl,
regardless of declaration matches. */
COPY_DECL_RTL (olddecl, newdecl);
set_builtin_decl_declared_p (fncode, true);
break;
}
- }
- copy_attributes_to_builtin (newdecl);
+ copy_attributes_to_builtin (newdecl);
+ }
}
if (new_defines_function)
/* If defining a function declared with other language
return NULL;
}
+ if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == CONCEPT_DECL)
+ return G_("redefinition of %q#D");
+
if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) != FUNCTION_DECL
|| (DECL_TEMPLATE_RESULT (newdecl)
== DECL_TEMPLATE_RESULT (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)
location_t switch_location;
/* Emit warnings as needed. */
- switch_location = cp_expr_loc_or_loc (cs->switch_stmt, input_location);
+ switch_location = cp_expr_loc_or_input_loc (cs->switch_stmt);
const bool bool_cond_p
= (SWITCH_STMT_TYPE (cs->switch_stmt)
&& TREE_CODE (SWITCH_STMT_TYPE (cs->switch_stmt)) == BOOLEAN_TYPE);
value = mark_rvalue_use (value);
+ if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type))
+ type = type_promotes_to (type);
+
+ tree ovalue = value;
+ /* The constant-expression VALUE shall be a converted constant expression
+ of the adjusted type of the switch condition, which doesn't allow
+ narrowing conversions. */
+ value = build_converted_constant_expr (type, value, tf_warning_or_error);
+
if (cxx_dialect >= cxx11
&& (SCOPED_ENUM_P (type)
- || !INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (value))))
- {
- if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type))
- type = type_promotes_to (type);
- value = (perform_implicit_conversion_flags
- (type, value, tf_warning_or_error,
- LOOKUP_IMPLICIT | LOOKUP_NO_NON_INTEGRAL));
- }
+ || !INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (ovalue))))
+ /* Use the converted value. */;
+ else
+ /* The already integral case. */
+ value = ovalue;
+
return cxx_constant_value (value);
}
{"value", &value_identifier, cik_normal},
{"_FUN", &fun_identifier, cik_normal},
{"__closure", &closure_identifier, cik_normal},
+ {"heap uninit", &heap_uninit_identifier, cik_normal},
+ {"heap ", &heap_identifier, cik_normal},
+ {"heap deleted", &heap_deleted_identifier, cik_normal},
{NULL, NULL, cik_normal}
};
deltype = build_exception_variant (deltype, empty_except_spec);
tree opnew = push_cp_library_fn (NEW_EXPR, newtype, 0);
DECL_IS_MALLOC (opnew) = 1;
- DECL_IS_OPERATOR_NEW (opnew) = 1;
+ DECL_SET_IS_OPERATOR_NEW (opnew, true);
opnew = push_cp_library_fn (VEC_NEW_EXPR, newtype, 0);
DECL_IS_MALLOC (opnew) = 1;
- DECL_IS_OPERATOR_NEW (opnew) = 1;
- push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW);
- push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW);
+ DECL_SET_IS_OPERATOR_NEW (opnew, true);
+ tree opdel = push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW);
+ DECL_SET_IS_OPERATOR_DELETE (opdel, true);
+ opdel = push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW);
+ DECL_SET_IS_OPERATOR_DELETE (opdel, true);
if (flag_sized_deallocation)
{
/* Also push the sized deallocation variants:
deltype = cp_build_type_attribute_variant (void_ftype_ptr_size,
extvisattr);
deltype = build_exception_variant (deltype, empty_except_spec);
- push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW);
- push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW);
+ opdel = push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW);
+ DECL_SET_IS_OPERATOR_DELETE (opdel, true);
+ opdel = push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW);
+ DECL_SET_IS_OPERATOR_DELETE (opdel, true);
}
if (aligned_new_threshold)
newtype = build_exception_variant (newtype, new_eh_spec);
opnew = push_cp_library_fn (NEW_EXPR, newtype, 0);
DECL_IS_MALLOC (opnew) = 1;
- DECL_IS_OPERATOR_NEW (opnew) = 1;
+ DECL_SET_IS_OPERATOR_NEW (opnew, true);
opnew = push_cp_library_fn (VEC_NEW_EXPR, newtype, 0);
DECL_IS_MALLOC (opnew) = 1;
- DECL_IS_OPERATOR_NEW (opnew) = 1;
+ DECL_SET_IS_OPERATOR_NEW (opnew, true);
/* operator delete (void *, align_val_t); */
deltype = build_function_type_list (void_type_node, ptr_type_node,
align_type_node, NULL_TREE);
deltype = cp_build_type_attribute_variant (deltype, extvisattr);
deltype = build_exception_variant (deltype, empty_except_spec);
- push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW);
- push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW);
+ opdel = push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW);
+ DECL_SET_IS_OPERATOR_DELETE (opdel, true);
+ opdel = push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW);
+ DECL_SET_IS_OPERATOR_DELETE (opdel, true);
if (flag_sized_deallocation)
{
NULL_TREE);
deltype = cp_build_type_attribute_variant (deltype, extvisattr);
deltype = build_exception_variant (deltype, empty_except_spec);
- push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW);
- push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW);
+ opdel = push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW);
+ DECL_SET_IS_OPERATOR_DELETE (opdel, true);
+ opdel = push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW);
+ DECL_SET_IS_OPERATOR_DELETE (opdel, true);
}
}
static tree
cp_make_fname_decl (location_t loc, tree id, int type_dep)
{
- const char *const name = (type_dep && in_template_function ()
- ? NULL : fname_as_string (type_dep));
+ const char * name = NULL;
+ bool release_name = false;
+ if (!(type_dep && in_template_function ()))
+ {
+ if (current_function_decl == NULL_TREE)
+ name = "top level";
+ else if (type_dep == 1) /* __PRETTY_FUNCTION__ */
+ name = cxx_printable_name (current_function_decl, 2);
+ else if (type_dep == 0) /* __FUNCTION__ */
+ {
+ name = fname_as_string (type_dep);
+ release_name = true;
+ }
+ else
+ gcc_unreachable ();
+ }
tree type;
tree init = cp_fname_init (name, &type);
tree decl = build_decl (loc, VAR_DECL, id, type);
- if (name)
+ if (release_name)
free (CONST_CAST (char *, name));
/* As we're using pushdecl_with_scope, we must set the context. */
class_type, class_key_or_enum_as_string (class_type));
}
+/* Returns the cv-qualifiers that apply to the type specified
+ by the DECLSPECS. */
+
+static int
+get_type_quals (const cp_decl_specifier_seq *declspecs)
+{
+ int type_quals = TYPE_UNQUALIFIED;
+
+ if (decl_spec_seq_has_spec_p (declspecs, ds_const))
+ type_quals |= TYPE_QUAL_CONST;
+ if (decl_spec_seq_has_spec_p (declspecs, ds_volatile))
+ type_quals |= TYPE_QUAL_VOLATILE;
+ if (decl_spec_seq_has_spec_p (declspecs, ds_restrict))
+ type_quals |= TYPE_QUAL_RESTRICT;
+
+ return type_quals;
+}
+
/* Make sure that a declaration with no declarator is well-formed, i.e.
just declares a tagged type or anonymous union.
bool error_p = false;
if (declspecs->multiple_types_p)
- error ("multiple types in one declaration");
+ error_at (smallest_type_location (declspecs),
+ "multiple types in one declaration");
else if (declspecs->redefined_builtin_type)
{
if (!in_system_header_at (input_location))
/* Anonymous unions are objects, so they can have specifiers. */;
SET_ANON_AGGR_TYPE_P (declared_type);
- if (TREE_CODE (declared_type) != UNION_TYPE
- && !in_system_header_at (input_location))
- pedwarn (input_location, OPT_Wpedantic, "ISO C++ prohibits anonymous structs");
+ if (TREE_CODE (declared_type) != UNION_TYPE)
+ pedwarn (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (declared_type)),
+ OPT_Wpedantic, "ISO C++ prohibits anonymous structs");
}
else
else if (decl_spec_seq_has_spec_p (declspecs, ds_constexpr))
error_at (declspecs->locations[ds_constexpr],
"%<constexpr%> cannot be used for type declarations");
+ else if (decl_spec_seq_has_spec_p (declspecs, ds_constinit))
+ error_at (declspecs->locations[ds_constinit],
+ "%<constinit%> cannot be used for type declarations");
}
if (declspecs->attributes && warn_attributes && declared_type)
&& TREE_CODE (decl) == TYPE_DECL)
{
error_at (DECL_SOURCE_LOCATION (decl),
- "typedef %qD is initialized (use decltype instead)", decl);
+ "typedef %qD is initialized (use %qs instead)",
+ decl, "decltype");
return error_mark_node;
}
&& 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)))
{
decl = maybe_push_decl (decl);
if (processing_template_decl)
- decl = push_template_decl (decl);
+ {
+ /* Make sure that for a `constinit' decl push_template_decl creates
+ a DECL_TEMPLATE_INFO info for us, so that cp_finish_decl can then set
+ TINFO_VAR_DECLARED_CONSTINIT. */
+ if (decl_spec_seq_has_spec_p (declspecs, ds_constinit))
+ retrofit_lang_decl (decl);
+ decl = push_template_decl (decl);
+ }
if (decl == error_mark_node)
return error_mark_node;
sorry ("non-trivial designated initializers not supported");
}
else
- error ("C99 designator %qE is not an integral constant-expression",
- ce->index);
+ error_at (cp_expr_loc_or_input_loc (ce->index),
+ "C99 designator %qE is not an integral constant-expression",
+ ce->index);
return false;
}
{
if (complain & tf_error)
show_notes = permerror (DECL_SOURCE_LOCATION (decl),
- "uninitialized const %qD", decl);
+ "uninitialized %<const %D%>", decl);
}
else
{
/* 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))
+ if ((POINTER_TYPE_P (elt_type) != POINTER_TYPE_P (init_type)))
+ last_nonzero = index;
+ else if (!type_initializer_zero_p (elt_type, elt_init))
last_nonzero = index;
/* This can happen with an invalid initializer (c++/54501). */
if (d->cur->index)
{
if (complain & tf_error)
- error ("C99 designator %qE outside aggregate initializer",
- d->cur->index);
+ error_at (cp_expr_loc_or_input_loc (d->cur->index),
+ "C99 designator %qE outside aggregate initializer",
+ d->cur->index);
else
return true;
}
static tree
check_initializer (tree decl, tree init, int flags, vec<tree, va_gc> **cleanups)
{
- tree type = TREE_TYPE (decl);
+ tree type;
tree init_code = NULL;
tree core_type;
about aggregate initialization of non-aggregate classes. */
flags |= LOOKUP_ALREADY_DIGESTED;
}
- else if (DECL_DECLARED_CONSTEXPR_P (decl))
+ else if (DECL_DECLARED_CONSTEXPR_P (decl)
+ || (flags & LOOKUP_CONSTINIT))
{
- /* Declared constexpr, but no suitable initializer; massage
- init appropriately so we can pass it into store_init_value
- for the error. */
+ /* Declared constexpr or constinit, but no suitable initializer;
+ massage init appropriately so we can pass it into
+ store_init_value for the error. */
if (CLASS_TYPE_P (type)
&& (!init || TREE_CODE (init) == TREE_LIST))
{
return NULL_TREE;
}
+/* Return true if DECL has either a trivial destructor, or for C++2A
+ is constexpr and has a constexpr destructor. */
+
+static bool
+decl_maybe_constant_destruction (tree decl, tree type)
+{
+ return (TYPE_HAS_TRIVIAL_DESTRUCTOR (type)
+ || (cxx_dialect >= cxx2a
+ && VAR_P (decl)
+ && DECL_DECLARED_CONSTEXPR_P (decl)
+ && type_has_constexpr_destructor (strip_array_types (type))));
+}
+
/* Finish processing of a declaration;
install its line number and initial value.
If the length of an array type is not known before,
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;
}
DECL_INITIAL (decl) = NULL_TREE;
}
+ /* Handle `constinit' on variable templates. */
+ if (flags & LOOKUP_CONSTINIT)
+ TINFO_VAR_DECLARED_CONSTINIT (DECL_TEMPLATE_INFO (decl)) = true;
+
/* Generally, initializers in templates are expanded when the
template is instantiated. But, if DECL is a variable constant
then it can be used in future constant expressions, so its value
if (VAR_P (decl))
{
+ duration_kind dk = decl_storage_duration (decl);
+ /* [dcl.constinit]/1 "The constinit specifier shall be applied
+ only to a declaration of a variable with static or thread storage
+ duration." */
+ if ((flags & LOOKUP_CONSTINIT)
+ && !(dk == dk_thread || dk == dk_static))
+ {
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "%<constinit%> can only be applied to a variable with "
+ "static or thread storage duration");
+ return;
+ }
+
/* If this is a local variable that will need a mangled name,
register it now. We must do this before processing the
initializer for the variable, since the initialization might
TREE_READONLY (decl) = 1;
/* Likewise if it needs destruction. */
- if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+ if (!decl_maybe_constant_destruction (decl, type))
TREE_READONLY (decl) = 0;
}
DECL_ATTRIBUTES (decl));
complete_type (TREE_TYPE (decl));
if (!cp_omp_mappable_type (TREE_TYPE (decl)))
- error ("%q+D in declare target directive does not have mappable type",
- decl);
+ {
+ error ("%q+D in declare target directive does not have mappable"
+ " type", decl);
+ cp_omp_emit_unmappable_type_notes (TREE_TYPE (decl));
+ }
else if (!lookup_attribute ("omp declare target",
DECL_ATTRIBUTES (decl))
&& !lookup_attribute ("omp declare target link",
}
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,
based on the actual type of the variable, so store it in a hash table. */
static GTY((cache)) tree_cache_map *decomp_type_table;
-static void
-store_decomp_type (tree v, tree t)
-{
- if (!decomp_type_table)
- decomp_type_table = tree_cache_map::create_ggc (13);
- decomp_type_table->put (v, t);
-}
tree
lookup_decomp_type (tree v)
{
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);
goto error_out;
}
/* Save the decltype away before reference collapse. */
- store_decomp_type (v[i], eltype);
+ hash_map_safe_put<hm_ggc> (decomp_type_table, v[i], eltype);
eltype = cp_build_reference_type (eltype, !lvalue_p (init));
TREE_TYPE (v[i]) = eltype;
layout_decl (v[i], 0);
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 (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
return void_node;
+ if (decl_maybe_constant_destruction (decl, type)
+ && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl))
+ {
+ cxx_maybe_build_cleanup (decl, tf_warning_or_error);
+ return void_node;
+ }
+
/* If we're using "__cxa_atexit" (or "__cxa_thread_atexit" or
"__aeabi_atexit"), and DECL is a class object, we can just pass the
destructor to "__cxa_atexit"; we don't have to build a temporary
gcc_assert (TREE_STATIC (decl));
/* Some variables require no dynamic initialization. */
- if (TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
+ if (decl_maybe_constant_destruction (decl, TREE_TYPE (decl)))
{
/* Make sure the destructor is callable. */
cxx_maybe_build_cleanup (decl, tf_warning_or_error);
if (location == UNKNOWN_LOCATION)
location = input_location;
- // Was the concept specifier present?
+ /* Was the concept specifier present? */
bool concept_p = inlinep & 4;
- // Concept declarations must have a corresponding definition.
+ /* Concept declarations must have a corresponding definition. */
if (concept_p && !funcdef_flag)
{
error_at (location, "concept %qD has no definition", declarator);
tree tmpl_reqs = NULL_TREE;
if (processing_template_decl > template_class_depth (ctype))
tmpl_reqs = TEMPLATE_PARMS_CONSTRAINTS (current_template_parms);
-
- /* Adjust the required expression into a constraint. */
- if (decl_reqs)
- decl_reqs = normalize_expression (decl_reqs);
-
tree ci = build_constraints (tmpl_reqs, decl_reqs);
+ if (concept_p && ci)
+ {
+ error_at (location, "a function concept cannot be constrained");
+ ci = NULL_TREE;
+ }
set_constraints (decl, ci);
}
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))
if (TREE_PURPOSE (t)
- && TREE_CODE (TREE_PURPOSE (t)) == DEFAULT_ARG)
+ && TREE_CODE (TREE_PURPOSE (t)) == DEFERRED_PARSE)
{
- error_at (defarg_location (TREE_PURPOSE (t)),
+ error_at (defparse_location (TREE_PURPOSE (t)),
"default arguments are not allowed in declaration "
"of friend template specialization %qD",
decl);
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 */
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. */
if (!same_type_ignoring_top_level_qualifiers_p (type, boolean_type_node))
error_at (declspecs->locations[ds_type_spec],
"concept must have type %<bool%>");
+ if (TEMPLATE_PARMS_CONSTRAINTS (current_template_parms))
+ {
+ error_at (location, "a variable concept cannot be constrained");
+ TEMPLATE_PARMS_CONSTRAINTS (current_template_parms) = NULL_TREE;
+ }
}
else if (flag_concepts
&& processing_template_decl > template_class_depth (scope))
{
tree reqs = TEMPLATE_PARMS_CONSTRAINTS (current_template_parms);
tree ci = build_constraints (reqs, NULL_TREE);
+
set_constraints (decl, ci);
}
TYPE_PTRMEMFUNC_FLAG (t) = 1;
field = build_decl (input_location, FIELD_DECL, pfn_identifier, type);
+ DECL_NONADDRESSABLE_P (field) = 1;
fields = field;
field = build_decl (input_location, FIELD_DECL, delta_identifier,
delta_type_node);
+ DECL_NONADDRESSABLE_P (field) = 1;
DECL_CHAIN (field) = fields;
fields = field;
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]);
+}
+
+static location_t
+smallest_type_location (const cp_decl_specifier_seq *declspecs)
+{
+ int type_quals = get_type_quals (declspecs);
+ return smallest_type_location (type_quals, declspecs->locations);
+}
+
/* 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:
error-recovery purposes. */
tree
-check_var_type (tree identifier, tree type)
+check_var_type (tree identifier, tree type, location_t loc)
{
if (VOID_TYPE_P (type))
{
if (!identifier)
- error ("unnamed variable or field declared void");
+ error_at (loc, "unnamed variable or field declared void");
else if (identifier_p (identifier))
{
gcc_assert (!IDENTIFIER_ANY_OP_P (identifier));
- error ("variable or field %qE declared void", identifier);
+ error_at (loc, "variable or field %qE declared void",
+ identifier);
}
else
- error ("variable or field declared void");
+ error_at (loc, "variable or field declared void");
type = error_mark_node;
}
/* 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;
tree type = NULL_TREE;
int longlong = 0;
int explicit_intN = 0;
+ int int_n_alt = 0;
int virtualp, explicitp, friendp, inlinep, staticp;
int explicit_int = 0;
int explicit_char = 0;
a member function. */
cp_ref_qualifier rqual = REF_QUAL_NONE;
/* cv-qualifiers that apply to the type specified by the DECLSPECS. */
- int type_quals = TYPE_UNQUALIFIED;
+ int type_quals = get_type_quals (declspecs);
tree raises = NULL_TREE;
int template_count = 0;
tree returned_attrs = NULL_TREE;
bool template_parm_flag = false;
bool typedef_p = decl_spec_seq_has_spec_p (declspecs, ds_typedef);
bool constexpr_p = decl_spec_seq_has_spec_p (declspecs, ds_constexpr);
+ bool constinit_p = decl_spec_seq_has_spec_p (declspecs, ds_constinit);
bool late_return_type_p = false;
bool array_parameter_p = false;
- location_t saved_loc = input_location;
tree reqs = NULL_TREE;
signed_p = decl_spec_seq_has_spec_p (declspecs, ds_signed);
long_p = decl_spec_seq_has_spec_p (declspecs, ds_long);
longlong = decl_spec_seq_has_spec_p (declspecs, ds_long_long);
explicit_intN = declspecs->explicit_intN_p;
+ int_n_alt = declspecs->int_n_alt;
thread_p = decl_spec_seq_has_spec_p (declspecs, ds_thread);
// Was concept_p specified? Note that ds_concept
if (concept_p)
constexpr_p = true;
- if (decl_spec_seq_has_spec_p (declspecs, ds_const))
- type_quals |= TYPE_QUAL_CONST;
- if (decl_spec_seq_has_spec_p (declspecs, ds_volatile))
- type_quals |= TYPE_QUAL_VOLATILE;
- if (decl_spec_seq_has_spec_p (declspecs, ds_restrict))
- type_quals |= TYPE_QUAL_RESTRICT;
-
if (decl_context == FUNCDEF)
funcdef_flag = true, decl_context = NORMAL;
else if (decl_context == MEMFUNCDEF)
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;
ctype = qualifying_scope;
if (!MAYBE_CLASS_TYPE_P (ctype))
{
- error ("%q#T is not a class or a namespace", ctype);
+ error_at (id_declarator->id_loc,
+ "%q#T is not a class or namespace", ctype);
ctype = NULL_TREE;
}
else if (innermost_code != cdk_function
&& !uniquely_derived_from_p (ctype,
current_class_type))
{
- error ("invalid use of qualified-name %<%T::%D%>",
- qualifying_scope, decl);
+ error_at (id_declarator->id_loc,
+ "invalid use of qualified-name %<%T::%D%>",
+ qualifying_scope, decl);
return error_mark_node;
}
}
{
if (innermost_code != cdk_function)
{
- error ("declaration of %qD as non-function", decl);
+ error_at (EXPR_LOCATION (decl),
+ "declaration of %qE as non-function", decl);
return error_mark_node;
}
else if (!qualifying_scope
&& !(current_class_type && at_class_scope_p ()))
{
- error ("declaration of %qD as non-member", decl);
+ error_at (EXPR_LOCATION (decl),
+ "declaration of %qE as non-member", decl);
return error_mark_node;
}
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;
}
}
return error_mark_node;
}
+ if (constinit_p && typedef_p)
+ {
+ error_at (declspecs->locations[ds_constinit],
+ "%<constinit%> cannot appear in a typedef declaration");
+ return error_mark_node;
+ }
+
+ /* [dcl.spec]/2 "At most one of the constexpr, consteval, and constinit
+ keywords shall appear in a decl-specifier-seq." */
+ if (constinit_p && constexpr_p)
+ {
+ gcc_rich_location richloc (declspecs->locations[ds_constinit]);
+ richloc.add_range (declspecs->locations[ds_constexpr]);
+ error_at (&richloc,
+ "can use at most one of the %<constinit%> and %<constexpr%> "
+ "specifiers");
+ return error_mark_node;
+ }
+
/* If there were multiple types specified in the decl-specifier-seq,
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;
}
cp_warn_deprecated_use (type);
if (type && TREE_CODE (type) == TYPE_DECL)
{
+ cp_warn_deprecated_use_scopes (CP_DECL_CONTEXT (type));
typedef_decl = type;
type = TREE_TYPE (typedef_decl);
if (DECL_ARTIFICIAL (typedef_decl))
else if (in_system_header_at (input_location) || flag_ms_extensions)
/* Allow it, sigh. */;
else if (! is_main)
- permerror (input_location, "ISO C++ forbids declaration of %qs with no type", name);
+ permerror (id_loc, "ISO C++ forbids declaration of %qs with no type",
+ name);
else if (pedantic)
- pedwarn (input_location, OPT_Wpedantic,
+ pedwarn (id_loc, OPT_Wpedantic,
"ISO C++ forbids declaration of %qs with no type", name);
else
- warning (OPT_Wreturn_type,
- "ISO C++ forbids declaration of %qs with no type", name);
+ warning_at (id_loc, OPT_Wreturn_type,
+ "ISO C++ forbids declaration of %qs with no type", name);
if (type_was_error_mark_node && template_parm_flag)
/* FIXME we should be able to propagate the error_mark_node as is
{
if (! int_n_enabled_p[declspecs->int_n_idx])
{
- error ("%<__int%d%> is not supported by this target",
- int_n_data[declspecs->int_n_idx].bitsize);
+ error_at (declspecs->locations[ds_type_spec],
+ "%<__int%d%> is not supported by this target",
+ int_n_data[declspecs->int_n_idx].bitsize);
explicit_intN = false;
}
- else if (pedantic && ! in_system_header_at (input_location))
- pedwarn (input_location, OPT_Wpedantic,
+ /* Don't pedwarn if the alternate "__intN__" form has been used instead
+ of "__intN". */
+ else if (!int_n_alt && pedantic && ! in_system_header_at (input_location))
+ pedwarn (declspecs->locations[ds_type_spec], OPT_Wpedantic,
"ISO C++ does not support %<__int%d%> for %qs",
int_n_data[declspecs->int_n_idx].bitsize, name);
}
if (decl_spec_seq_has_spec_p (declspecs, ds_complex))
{
if (TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE)
- error ("complex invalid for %qs", name);
+ error_at (declspecs->locations[ds_complex],
+ "complex invalid for %qs", name);
/* If a modifier is specified, the resulting complex is the complex
form of TYPE. E.g, "complex short" is "complex short int". */
else if (type == integer_type_node)
"a parameter cannot be declared %<constexpr%>");
constexpr_p = 0;
}
+ else if (constinit_p)
+ {
+ error_at (declspecs->locations[ds_constinit],
+ "a parameter cannot be declared %<constinit%>");
+ constexpr_p = 0;
+ }
}
/* Give error if `virtual' is used outside of class declaration. */
? 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");
+ /* [dcl.struct.bind] "A cv that includes volatile is deprecated." */
+ if (type_quals & TYPE_QUAL_VOLATILE)
+ warning_at (declspecs->locations[ds_volatile], OPT_Wvolatile,
+ "%<volatile%>-qualified structured binding is deprecated");
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. */
&& storage_class != sc_static)
|| typedef_p))
{
- error ("multiple storage classes in declaration of %qs", name);
+ location_t loc
+ = min_location (declspecs->locations[ds_thread],
+ declspecs->locations[ds_storage_class]);
+ error_at (loc, "multiple storage classes in declaration of %qs", name);
thread_p = false;
}
if (decl_context != NORMAL
else if (toplevel_bindings_p ())
{
if (storage_class == sc_auto)
- error ("top-level declaration of %qs specifies %<auto%>", name);
+ error_at (declspecs->locations[ds_storage_class],
+ "top-level declaration of %qs specifies %<auto%>", name);
}
else if (thread_p
&& storage_class != sc_extern
type = create_array_type_for_decl (dname, type,
declarator->u.array.bounds,
declarator->id_loc);
- if (!valid_array_size_p (input_location, type, dname))
+ if (!valid_array_size_p (dname
+ ? declarator->id_loc : input_location,
+ type, dname))
type = error_mark_node;
if (declarator->std_attributes)
/* Declaring a function type. */
- input_location = declspecs->locations[ds_type_spec];
- abstract_virtuals_error (ACU_RETURN, type);
- input_location = saved_loc;
+ {
+ iloc_sentinel ils (declspecs->locations[ds_type_spec]);
+ abstract_virtuals_error (ACU_RETURN, type);
+ }
/* Pick up type qualifiers which should be applied to `this'. */
memfn_quals = declarator->u.function.qualifiers;
else if (late_return_type
&& sfk != sfk_conversion)
{
+ if (late_return_type == error_mark_node)
+ return error_mark_node;
if (cxx_dialect < cxx11)
/* Not using maybe_warn_cpp0x because this should
always be an error. */
if (SCALAR_TYPE_P (type) || VOID_TYPE_P (type))
warning_at (typespec_loc, OPT_Wignored_qualifiers, "type "
"qualifiers ignored on function return type");
+ /* [dcl.fct] "A volatile-qualified return type is
+ deprecated." */
+ if (type_quals & TYPE_QUAL_VOLATILE)
+ warning_at (typespec_loc, OPT_Wvolatile,
+ "%<volatile%>-qualified return type is "
+ "deprecated");
+
/* We now know that the TYPE_QUALS don't apply to the
decl, but to its return type. */
type_quals = TYPE_UNQUALIFIED;
"an array", name);
return error_mark_node;
}
+ if (constinit_p)
+ {
+ error_at (declspecs->locations[ds_constinit],
+ "%<constinit%> on function return type is not "
+ "allowed");
+ return error_mark_node;
+ }
+ /* Only plain decltype(auto) is allowed. */
+ if (tree a = type_uses_auto (type))
+ {
+ if (AUTO_IS_DECLTYPE (a) && a != type)
+ {
+ error_at (typespec_loc, "%qT as type rather than "
+ "plain %<decltype(auto)%>", type);
+ return error_mark_node;
+ }
+ }
if (ctype == NULL_TREE
&& decl_context == FIELD
virtual. A constructor may not be static.
A constructor may not be declared with ref-qualifier. */
if (staticp == 2)
- error ((flags == DTOR_FLAG)
- ? G_("destructor cannot be static member function")
- : G_("constructor cannot be static member function"));
+ error_at (declspecs->locations[ds_storage_class],
+ (flags == DTOR_FLAG)
+ ? G_("destructor cannot be static member "
+ "function")
+ : G_("constructor cannot be static member "
+ "function"));
if (memfn_quals)
{
error ((flags == DTOR_FLAG)
friendp = 0;
}
if (decl_context == NORMAL)
- error ("friend declaration not in class definition");
+ error_at (declarator->id_loc,
+ "friend declaration not in class definition");
if (current_function_decl && funcdef_flag)
{
- error ("can%'t define friend function %qs in a local "
- "class definition", name);
+ error_at (declarator->id_loc,
+ "cannot define friend function %qs in a local "
+ "class definition", name);
friendp = 0;
}
+ /* [class.friend]/6: A function can be defined in a friend
+ declaration if the function name is unqualified. */
+ if (funcdef_flag && in_namespace)
+ {
+ if (in_namespace == global_namespace)
+ error_at (declarator->id_loc,
+ "friend function definition %qs cannot have "
+ "a name qualified with %<::%>", name);
+ else
+ error_at (declarator->id_loc,
+ "friend function definition %qs cannot have "
+ "a name qualified with %<%D::%>", name,
+ in_namespace);
+ }
}
else if (ctype && sfk == sfk_conversion)
{
&& inner_declarator->u.id.sfk == sfk_destructor
&& arg_types != void_list_node)
{
- error ("destructors may not have parameters");
+ error_at (declarator->id_loc,
+ "destructors may not have parameters");
arg_types = void_list_node;
parms = NULL_TREE;
}
}
}
+ 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 (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;
}
}
}
- location_t loc = declarator ? declarator->id_loc : input_location;
-
/* If this is declaring a typedef name, return a TYPE_DECL. */
if (typedef_p && decl_context != TYPENAME)
{
bool alias_p = decl_spec_seq_has_spec_p (declspecs, ds_alias);
tree decl;
+ if (funcdef_flag)
+ {
+ if (decl_context == NORMAL)
+ error_at (id_loc,
+ "typedef may not be a function definition");
+ else
+ error_at (id_loc,
+ "typedef may not be a member function definition");
+ return error_mark_node;
+ }
+
/* This declaration:
typedef void f(int) const;
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_loc (loc, TYPE_DECL, unqualified_id, type);
+ decl = build_lang_decl_loc (id_loc, TYPE_DECL, unqualified_id, type);
else
- decl = build_decl (loc, 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;
}
error message later. */
if (decl_context != PARM)
{
- type = check_var_type (unqualified_id, type);
+ type = check_var_type (unqualified_id, type, id_loc);
if (type == error_mark_node)
return error_mark_node;
}
if (ctype || in_namespace)
error ("cannot use %<::%> in parameter declaration");
- if (type_uses_auto (type)
- && !(cxx_dialect >= cxx17 && template_parm_flag))
+ tree auto_node = type_uses_auto (type);
+ if (auto_node && !(cxx_dialect >= cxx17 && template_parm_flag))
{
if (cxx_dialect >= cxx14)
- error ("%<auto%> parameter not permitted in this context");
+ {
+ if (decl_context == PARM && AUTO_IS_DECLTYPE (auto_node))
+ error_at (typespec_loc,
+ "cannot declare a parameter with %<decltype(auto)%>");
+ else
+ error_at (typespec_loc,
+ "%<auto%> parameter not permitted in this context");
+ }
else
- error ("parameter declared %<auto%>");
+ error_at (typespec_loc, "parameter declared %<auto%>");
type = error_mark_node;
}
&& (TREE_CODE (ctype) == UNION_TYPE
|| TREE_CODE (ctype) == QUAL_UNION_TYPE))
{
- error ("flexible array member in union");
+ error_at (id_loc, "flexible array member in union");
type = error_mark_node;
}
else
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,
else if (in_namespace && !friendp)
{
/* Something like struct S { int N::j; }; */
- error ("invalid use of %<::%>");
+ error_at (id_loc, "invalid use of %<::%>");
return error_mark_node;
}
else if (FUNC_OR_METHOD_TYPE_P (type) && unqualified_id)
if (!ctype)
{
gcc_assert (friendp);
- error ("expected qualified name in friend declaration "
- "for destructor %qD", uqname);
+ error_at (id_loc, "expected qualified name in friend "
+ "declaration for destructor %qD", uqname);
return error_mark_node;
}
if (!check_dtor_name (ctype, TREE_OPERAND (uqname, 0)))
{
- error ("declaration of %qD as member of %qT",
- uqname, ctype);
+ error_at (id_loc, "declaration of %qD as member of %qT",
+ uqname, ctype);
return error_mark_node;
}
if (concept_p)
"a destructor cannot be %<concept%>");
return error_mark_node;
}
- if (constexpr_p)
- {
- error_at (declspecs->locations[ds_constexpr],
- "a destructor cannot be %<constexpr%>");
- return error_mark_node;
- }
+ if (constexpr_p && cxx_dialect < cxx2a)
+ {
+ error_at (declspecs->locations[ds_constexpr],
+ "%<constexpr%> destructors only available"
+ " with %<-std=c++2a%> or %<-std=gnu++2a%>");
+ return error_mark_node;
+ }
}
else if (sfk == sfk_constructor && friendp && !ctype)
{
tree tmpl = TREE_OPERAND (unqualified_id, 0);
if (variable_template_p (tmpl))
{
- error ("specialization of variable template %qD "
- "declared as function", tmpl);
+ error_at (id_loc, "specialization of variable template "
+ "%qD declared as function", tmpl);
inform (DECL_SOURCE_LOCATION (tmpl),
"variable template declared here");
return error_mark_node;
}
/* Tell grokfndecl if it needs to set TREE_PUBLIC on the node. */
- function_context = (ctype != NULL_TREE) ?
- decl_function_context (TYPE_MAIN_DECL (ctype)) : NULL_TREE;
- publicp = (! friendp || ! staticp)
- && function_context == NULL_TREE;
+ function_context
+ = (ctype != NULL_TREE
+ ? decl_function_context (TYPE_MAIN_DECL (ctype)) : NULL_TREE);
+ publicp = ((! friendp || ! staticp)
+ && function_context == NULL_TREE);
decl = grokfndecl (ctype, type,
TREE_CODE (unqualified_id) != TEMPLATE_ID_EXPR
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)
{
- if (unqualified_id && declarator)
- error_at (declarator->id_loc,
+ if (unqualified_id)
+ error_at (id_loc,
"%qE is neither function nor member function; "
"cannot be declared friend", unqualified_id);
else
{
/* C++ allows static class members. All other work
for this is done by grokfield. */
- decl = build_lang_decl_loc (loc, VAR_DECL,
+ decl = build_lang_decl_loc (id_loc, VAR_DECL,
unqualified_id, type);
set_linkage_for_static_data_member (decl);
if (concept_p)
else if (constexpr_p)
{
error_at (declspecs->locations[ds_constexpr],
- "non-static data member %qE declared %<constexpr%>",
- unqualified_id);
+ "non-static data member %qE declared "
+ "%<constexpr%>", unqualified_id);
constexpr_p = false;
}
- decl = build_decl (loc, FIELD_DECL, unqualified_id, type);
+ else if (constinit_p)
+ {
+ error_at (declspecs->locations[ds_constinit],
+ "non-static data member %qE declared "
+ "%<constinit%>", unqualified_id);
+ constinit_p = false;
+ }
+ decl = build_decl (id_loc, FIELD_DECL, unqualified_id, type);
DECL_NONADDRESSABLE_P (decl) = bitfield;
if (bitfield && !unqualified_id)
{
// FIXME:gcc_assert (original_name == dname);
if (storage_class == sc_auto)
- error ("storage class %<auto%> invalid for function %qs", name);
+ error_at (declspecs->locations[ds_storage_class],
+ "storage class %<auto%> invalid for function %qs", name);
else if (storage_class == sc_register)
- error ("storage class %<register%> invalid for function %qs", name);
+ error_at (declspecs->locations[ds_storage_class],
+ "storage class %<register%> invalid for function %qs",
+ name);
else if (thread_p)
{
if (declspecs->gnu_thread_keyword_p)
funcdef_flag,
late_return_type_p,
template_count, in_namespace, attrlist,
- declarator->id_loc);
+ id_loc);
if (decl == NULL_TREE)
return error_mark_node;
concept_p,
template_count,
ctype ? ctype : in_namespace,
- loc);
+ id_loc);
if (decl == NULL_TREE)
return error_mark_node;
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);
}
tree var;
tree decl_type;
- if (TREE_CODE (arg) == DEFAULT_ARG)
- /* We get a DEFAULT_ARG when looking at an in-class declaration
+ if (TREE_CODE (arg) == DEFERRED_PARSE)
+ /* We get a DEFERRED_PARSE when looking at an in-class declaration
with a default argument. Ignore the argument for now; we'll
deal with it after the class is complete. */
return arg;
/* Avoid redundant -Wzero-as-null-pointer-constant warnings at
the call sites. */
if (TYPE_PTR_OR_PTRMEM_P (decl_type)
- && null_ptr_cst_p (arg))
+ && null_ptr_cst_p (arg)
+ /* Don't lose side-effects as in PR90473. */
+ && !TREE_SIDE_EFFECTS (arg))
return nullptr_node;
/* [dcl.fct.default]
if (TREE_DEPRECATED (TYPE_NAME (type)))
return type;
else
- return NULL_TREE;
+ {
+ cp_warn_deprecated_use_scopes (CP_DECL_CONTEXT (TYPE_NAME (type)));
+ return NULL_TREE;
+ }
}
/* Do warn about using typedefs to a deprecated class. */
cp_warn_deprecated_use (deptype);
}
+ /* [dcl.fct] "A parameter with volatile-qualified type is
+ deprecated." */
+ if (CP_TYPE_VOLATILE_P (type))
+ warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wvolatile,
+ "%<volatile%>-qualified parameter is "
+ "deprecated");
+
/* Top-level qualifiers on the parameters are
ignored for function types. */
type = cp_build_qualified_type (type, 0);
are no other parameters or else all other parameters have
default arguments. */
TYPE_HAS_COPY_CTOR (class_type) = 1;
- if (user_provided_p (decl))
- TYPE_HAS_COMPLEX_COPY_CTOR (class_type) = 1;
if (ctor > 1)
TYPE_HAS_CONST_COPY_CTOR (class_type) = 1;
}
else if (sufficient_parms_p (FUNCTION_FIRST_USER_PARMTYPE (decl)))
TYPE_HAS_DEFAULT_CONSTRUCTOR (class_type) = 1;
- else if (move_fn_p (decl) && user_provided_p (decl))
- TYPE_HAS_COMPLEX_MOVE_CTOR (class_type) = 1;
else if (is_list_ctor (decl))
TYPE_HAS_LIST_CTOR (class_type) = 1;
if (assop)
{
TYPE_HAS_COPY_ASSIGN (class_type) = 1;
- if (user_provided_p (decl))
- TYPE_HAS_COMPLEX_COPY_ASSIGN (class_type) = 1;
if (assop != 1)
TYPE_HAS_CONST_COPY_ASSIGN (class_type) = 1;
}
- else if (move_fn_p (decl) && user_provided_p (decl))
- TYPE_HAS_COMPLEX_MOVE_ASSIGN (class_type) = 1;
}
else if (IDENTIFIER_CONV_OP_P (DECL_NAME (decl)))
TYPE_HAS_CONVERSION (class_type) = true;
or implicitly defined), there's no need to worry about their
existence. Theoretically, they should never even be
instantiated, but that's hard to forestall. */
- error ("invalid constructor; you probably meant %<%T (const %T&)%>",
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "invalid constructor; you probably meant %<%T (const %T&)%>",
ctype, ctype);
return false;
}
}
if (op_flags & OVL_OP_FLAG_DELETE)
- coerce_delete_type (decl, loc);
+ {
+ DECL_SET_IS_OPERATOR_DELETE (decl, true);
+ coerce_delete_type (decl, loc);
+ }
else
{
- DECL_IS_OPERATOR_NEW (decl) = 1;
+ DECL_SET_IS_OPERATOR_NEW (decl, true);
TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl), loc);
}
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;
type of the enumeration. */
for (values = TYPE_VALUES (enumtype); values; values = TREE_CHAIN (values))
{
- location_t saved_location;
-
decl = TREE_VALUE (values);
- saved_location = input_location;
- input_location = DECL_SOURCE_LOCATION (decl);
+ iloc_sentinel ils (DECL_SOURCE_LOCATION (decl));
if (fixed_underlying_type_p)
/* If the enumeration type has a fixed underlying type, we
already checked all of the enumerator values. */
value = perform_implicit_conversion (underlying_type,
DECL_INITIAL (decl),
tf_warning_or_error);
- input_location = saved_location;
-
/* Do not clobber shared ints. */
if (value != error_mark_node)
{
if (! INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P
(TREE_TYPE (value)))
{
- error ("enumerator value for %qD must have integral or "
- "unscoped enumeration type", name);
+ error_at (cp_expr_loc_or_input_loc (value),
+ "enumerator value for %qD must have integral or "
+ "unscoped enumeration type", name);
value = NULL_TREE;
}
else
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))
invoke_plugin_callbacks (PLUGIN_START_PARSE_FUNCTION, decl1);
if (decl1 == error_mark_node)
return false;
- /* If the declarator is not suitable for a function definition,
- cause a syntax error. */
- if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL)
- {
- error ("invalid function declaration");
- return false;
- }
if (DECL_MAIN_P (decl1))
/* main must return int. grokfndecl should have corrected it
&& !DECL_DEFAULTED_FN (fn));
}
+/* Helper function to push ARGS into the current lexical scope. DECL
+ is the function declaration. NONPARMS is used to handle enum
+ constants. */
+
+void
+do_push_parm_decls (tree decl, tree args, tree *nonparms)
+{
+ /* If we're doing semantic analysis, then we'll call pushdecl
+ for each of these. We must do them in reverse order so that
+ they end in the correct forward order. */
+ args = nreverse (args);
+
+ tree next;
+ for (tree parm = args; parm; parm = next)
+ {
+ next = DECL_CHAIN (parm);
+ if (TREE_CODE (parm) == PARM_DECL)
+ pushdecl (parm);
+ else if (nonparms)
+ {
+ /* If we find an enum constant or a type tag, put it aside for
+ the moment. */
+ TREE_CHAIN (parm) = NULL_TREE;
+ *nonparms = chainon (*nonparms, parm);
+ }
+ }
+
+ /* Get the decls in their original chain order and record in the
+ function. This is all and only the PARM_DECLs that were
+ pushed into scope by the loop above. */
+ DECL_ARGUMENTS (decl) = get_local_decls ();
+}
+
/* Store the parameter declarations into the current function declaration.
This is called after parsing the parameter declarations, before
digesting the body of the function.
store_parm_decls (tree current_function_parms)
{
tree fndecl = current_function_decl;
- tree parm;
/* This is a chain of any other decls that came in among the parm
declarations. If a parm is declared with enum {foo, bar} x;
and complain if any redundant old-style parm decls were written. */
tree specparms = current_function_parms;
- tree next;
/* Must clear this because it might contain TYPE_DECLs declared
at class level. */
current_binding_level->names = NULL;
- /* If we're doing semantic analysis, then we'll call pushdecl
- for each of these. We must do them in reverse order so that
- they end in the correct forward order. */
- specparms = nreverse (specparms);
-
- for (parm = specparms; parm; parm = next)
- {
- next = DECL_CHAIN (parm);
- if (TREE_CODE (parm) == PARM_DECL)
- pushdecl (parm);
- else
- {
- /* If we find an enum constant or a type tag,
- put it aside for the moment. */
- TREE_CHAIN (parm) = NULL_TREE;
- nonparms = chainon (nonparms, parm);
- }
- }
-
- /* Get the decls in their original chain order and record in the
- function. This is all and only the PARM_DECLs that were
- pushed into scope by the loop above. */
- DECL_ARGUMENTS (fndecl) = get_local_decls ();
+ do_push_parm_decls (fndecl, specparms, &nonparms);
}
else
DECL_ARGUMENTS (fndecl) = NULL_TREE;
if (!processing_template_decl && FNDECL_USED_AUTO (fndecl)
&& TREE_TYPE (fntype) == DECL_SAVED_AUTO_RETURN_TYPE (fndecl))
{
- if (is_auto (DECL_SAVED_AUTO_RETURN_TYPE (fndecl)))
+ if (is_auto (DECL_SAVED_AUTO_RETURN_TYPE (fndecl))
+ && !current_function_returns_value
+ && !current_function_returns_null)
{
+ /* We haven't applied return type deduction because we haven't
+ seen any return statements. Do that now. */
+ tree node = type_uses_auto (DECL_SAVED_AUTO_RETURN_TYPE (fndecl));
+ do_auto_deduction (DECL_SAVED_AUTO_RETURN_TYPE (fndecl),
+ void_node, node, tf_warning_or_error,
+ adc_return_type);
+
apply_deduced_return_type (fndecl, void_type_node);
fntype = TREE_TYPE (fndecl);
}
&& same_type_ignoring_top_level_qualifiers_p
(TREE_TYPE (valtype), TREE_TYPE (current_class_ref))
&& global_dc->option_enabled (OPT_Wreturn_type,
+ global_dc->lang_mask,
global_dc->option_state))
add_return_star_this_fixit (&richloc, fndecl);
}
if (fndecl == error_mark_node)
return error_mark_node;
- if (fndecl == NULL || TREE_CODE (fndecl) != FUNCTION_DECL)
- {
- error ("invalid member function declaration");
- return error_mark_node;
- }
-
if (attrlist)
cplus_decl_attributes (&fndecl, attrlist, 0);
cleanup = error_mark_node;
else if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
/* Discard the call. */;
+ else if (decl_maybe_constant_destruction (decl, type)
+ && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl))
+ cxx_constant_dtor (call, decl);
else if (cleanup)
cleanup = cp_build_compound_expr (cleanup, call, complain);
else
the end of the block. So let's unset the location of the
destructor call instead. */
protected_set_expr_location (cleanup, UNKNOWN_LOCATION);
+ if (cleanup && CONVERT_EXPR_P (cleanup))
+ protected_set_expr_location (TREE_OPERAND (cleanup, 0), UNKNOWN_LOCATION);
if (cleanup
&& DECL_P (decl)
{
switch (TREE_CODE (&t->generic))
{
- case DEFAULT_ARG: return TS_CP_DEFAULT_ARG;
+ case ARGUMENT_PACK_SELECT: return TS_CP_ARGUMENT_PACK_SELECT;
+ case BASELINK: return TS_CP_BASELINK;
+ case CONSTRAINT_INFO: return TS_CP_CONSTRAINT_INFO;
case DEFERRED_NOEXCEPT: return TS_CP_DEFERRED_NOEXCEPT;
+ case DEFERRED_PARSE: return TS_CP_DEFERRED_PARSE;
case IDENTIFIER_NODE: return TS_CP_IDENTIFIER;
+ case LAMBDA_EXPR: return TS_CP_LAMBDA_EXPR;
case OVERLOAD: return TS_CP_OVERLOAD;
- case TEMPLATE_PARM_INDEX: return TS_CP_TPI;
case PTRMEM_CST: return TS_CP_PTRMEM;
- case BASELINK: return TS_CP_BASELINK;
- case TEMPLATE_DECL: return TS_CP_TEMPLATE_DECL;
case STATIC_ASSERT: return TS_CP_STATIC_ASSERT;
- case ARGUMENT_PACK_SELECT: return TS_CP_ARGUMENT_PACK_SELECT;
- case TRAIT_EXPR: return TS_CP_TRAIT_EXPR;
- case LAMBDA_EXPR: return TS_CP_LAMBDA_EXPR;
+ case TEMPLATE_DECL: return TS_CP_TEMPLATE_DECL;
case TEMPLATE_INFO: return TS_CP_TEMPLATE_INFO;
- case CONSTRAINT_INFO: return TS_CP_CONSTRAINT_INFO;
+ case TEMPLATE_PARM_INDEX: return TS_CP_TPI;
+ case TRAIT_EXPR: return TS_CP_TRAIT_EXPR;
case USERDEF_LITERAL: return TS_CP_USERDEF_LITERAL;
default: return TS_CP_GENERIC;
}
{
if (undeduced_auto_decl (decl))
{
- if (complain & tf_error)
+ if (TREE_NO_WARNING (decl) && seen_error ())
+ /* We probably already complained about deduction failure. */;
+ else if (complain & tf_error)
error ("use of %qD before deduction of %<auto%>", decl);
return false;
}