tree f2 = TREE_TYPE (olddecl);
tree p1 = TYPE_ARG_TYPES (f1);
tree p2 = TYPE_ARG_TYPES (f2);
+ tree r2;
/* Specializations of different templates are different functions
even if they have the same type. */
if (TREE_CODE (f1) != TREE_CODE (f2))
return 0;
- if (same_type_p (TREE_TYPE (f1), TREE_TYPE (f2)))
+ /* A declaration with deduced return type should use its pre-deduction
+ type for declaration matching. */
+ if (FNDECL_USED_AUTO (olddecl))
+ r2 = DECL_STRUCT_FUNCTION (olddecl)->language->x_auto_return_pattern;
+ else
+ r2 = TREE_TYPE (f2);
+
+ if (same_type_p (TREE_TYPE (f1), r2))
{
if (!prototype_p (f2) && DECL_EXTERN_C_P (olddecl)
&& (DECL_BUILT_IN (olddecl)
TYPE_ARG_TYPES (TREE_TYPE (olddecl))))
{
error ("new declaration %q#D", newdecl);
- error ("ambiguates old declaration %q+#D", olddecl);
+ if (FNDECL_USED_AUTO (olddecl))
+ error_at (DECL_SOURCE_LOCATION (olddecl), "ambiguates old "
+ "declaration with deduced return type");
+ else
+ error ("ambiguates old declaration %q+#D", olddecl);
return error_mark_node;
}
else
init_list_type_node = make_node (LANG_TYPE);
record_unknown_type (init_list_type_node, "init list");
- dependent_lambda_return_type_node = make_node (LANG_TYPE);
- record_unknown_type (dependent_lambda_return_type_node,
- "undeduced lambda return type");
-
{
/* Make sure we get a unique function type, so we can give
its pointer type a name. (This wins for gdb.) */
tree
check_tag_decl (cp_decl_specifier_seq *declspecs)
{
- int saw_friend = declspecs->specs[(int)ds_friend] != 0;
- int saw_typedef = declspecs->specs[(int)ds_typedef] != 0;
+ int saw_friend = decl_spec_seq_has_spec_p (declspecs, ds_friend);
+ int saw_typedef = decl_spec_seq_has_spec_p (declspecs, ds_typedef);
/* If a class, struct, or enum type is declared by the DECLSPECS
(i.e, if a class-specifier, enum-specifier, or non-typename
elaborated-type-specifier appears in the DECLSPECS),
else if (declspecs->redefined_builtin_type)
{
if (!in_system_header)
- permerror (input_location, "redeclaration of C++ built-in type %qT",
+ permerror (declspecs->locations[ds_redefined_builtin_type_spec],
+ "redeclaration of C++ built-in type %qT",
declspecs->redefined_builtin_type);
return NULL_TREE;
}
SET_ANON_AGGR_TYPE_P (declared_type);
if (TREE_CODE (declared_type) != UNION_TYPE && !in_system_header)
- pedwarn (input_location, OPT_pedantic, "ISO C++ prohibits anonymous structs");
+ pedwarn (input_location, OPT_Wpedantic, "ISO C++ prohibits anonymous structs");
}
else
{
- if (declspecs->specs[(int)ds_inline]
- || declspecs->specs[(int)ds_virtual])
+ if (decl_spec_seq_has_spec_p (declspecs, ds_inline)
+ || decl_spec_seq_has_spec_p (declspecs, ds_virtual))
error ("%qs can only be specified for functions",
- declspecs->specs[(int)ds_inline]
+ decl_spec_seq_has_spec_p (declspecs, ds_inline)
? "inline" : "virtual");
else if (saw_friend
&& (!current_class_type
|| current_scope () != current_class_type))
error ("%<friend%> can only be specified inside a class");
- else if (declspecs->specs[(int)ds_explicit])
+ else if (decl_spec_seq_has_spec_p (declspecs, ds_explicit))
error ("%<explicit%> can only be specified for constructors");
else if (declspecs->storage_class)
error ("a storage class can only be specified for objects "
"and functions");
- else if (declspecs->specs[(int)ds_const]
- || declspecs->specs[(int)ds_volatile]
- || declspecs->specs[(int)ds_restrict]
- || declspecs->specs[(int)ds_thread])
+ else if (decl_spec_seq_has_spec_p (declspecs, ds_const)
+ || decl_spec_seq_has_spec_p (declspecs, ds_volatile)
+ || decl_spec_seq_has_spec_p (declspecs, ds_restrict)
+ || decl_spec_seq_has_spec_p (declspecs, ds_thread))
error ("qualifiers can only be specified for objects "
"and functions");
else if (saw_typedef)
warning (0, "%<typedef%> was ignored in this declaration");
- else if (declspecs->specs[(int) ds_constexpr])
+ else if (decl_spec_seq_has_spec_p (declspecs, ds_constexpr))
error ("%<constexpr%> cannot be used for type declarations");
}
+ if (declspecs->attributes && warn_attributes && declared_type)
+ {
+ location_t loc;
+ if (!CLASS_TYPE_P (declared_type)
+ || !CLASSTYPE_TEMPLATE_INSTANTIATION (declared_type))
+ /* For a non-template class, use the name location. */
+ loc = location_of (declared_type);
+ else
+ /* For a template class (an explicit instantiation), use the
+ current location. */
+ loc = input_location;
+ warning_at (loc, OPT_Wattributes, "attribute ignored in declaration "
+ "of %q#T", declared_type);
+ inform (loc, "attribute for %q#T must follow the %qs keyword",
+ declared_type, class_key_or_enum_as_string (declared_type));
+ }
+
return declared_type;
}
if (!t)
return NULL_TREE;
- if (declspecs->attributes)
- {
- warning (0, "attribute ignored in declaration of %q+#T", t);
- warning (0, "attribute for %q+#T must follow the %qs keyword",
- t, class_key_or_enum_as_string (t));
-
- }
-
if (maybe_process_partial_specialization (t) == error_mark_node)
return NULL_TREE;
}
/* If #pragma weak was used, mark the decl weak now. */
- maybe_apply_pragma_weak (decl);
+ if (!processing_template_decl)
+ maybe_apply_pragma_weak (decl);
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_DECLARED_INLINE_P (decl)
error ("duplicate initialization of %qD", decl);
if (duplicate_decls (decl, field, /*newdecl_is_friend=*/false))
decl = field;
- if (declspecs->specs[(int) ds_constexpr]
+ if (decl_spec_seq_has_spec_p (declspecs, ds_constexpr)
&& !DECL_DECLARED_CONSTEXPR_P (field))
error ("%qD declared %<constexpr%> outside its class", field);
}
if (TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE
&& TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE)
/* Note: default conversion is only called in very special cases. */
- init = decay_conversion (init);
+ init = decay_conversion (init, tf_warning_or_error);
/* Convert INIT to the reference type TYPE. This may involve the
creation of a temporary, whose lifetime must be the same as that
return error_mark_node;
}
- field = lookup_field_1 (type, d->cur->index, /*want_type=*/false);
+ if (TREE_CODE (d->cur->index) == FIELD_DECL)
+ /* We already reshaped this. */
+ gcc_assert (d->cur->index == field);
+ else
+ field = lookup_field_1 (type, d->cur->index, /*want_type=*/false);
if (!field || TREE_CODE (field) != FIELD_DECL)
{
valid aggregate initialization. */
&& !first_initializer_p
&& (same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE (init))
- || can_convert_arg (type, TREE_TYPE (init), init, LOOKUP_NORMAL)))
+ || can_convert_arg (type, TREE_TYPE (init), init, LOOKUP_NORMAL,
+ complain)))
{
d->cur++;
return init;
&& (DECL_INITIAL (decl) || init))
DECL_INITIALIZED_IN_CLASS_P (decl) = 1;
- auto_node = type_uses_auto (type);
- if (auto_node)
+ if (TREE_CODE (decl) != FUNCTION_DECL
+ && (auto_node = type_uses_auto (type)))
{
tree d_init;
if (init == NULL_TREE)
atexit_fndecl = build_library_fn_ptr (name, fn_type);
mark_used (atexit_fndecl);
pop_lang_context ();
- atexit_node = decay_conversion (atexit_fndecl);
+ atexit_node = decay_conversion (atexit_fndecl, tf_warning_or_error);
return atexit_node;
}
if (ctype != NULL_TREE)
grokclassfn (ctype, decl, flags);
+ /* 12.4/3 */
+ if (cxx_dialect >= cxx0x
+ && DECL_DESTRUCTOR_P (decl)
+ && !TYPE_BEING_DEFINED (DECL_CONTEXT (decl))
+ && !processing_template_decl)
+ deduce_noexcept_on_destructor (decl);
+
decl = check_explicit_specialization (orig_declarator, decl,
template_count,
2 * funcdef_flag +
TREE_PUBLIC (decl) = DECL_EXTERNAL (decl);
}
- if (declspecs->specs[(int)ds_thread])
+ if (decl_spec_seq_has_spec_p (declspecs, ds_thread))
DECL_TLS_MODEL (decl) = decl_default_tls_model (decl);
/* If the type of the decl has no linkage, make sure that we'll
"static member %qD",
decl);
else if (!INTEGRAL_OR_ENUMERATION_TYPE_P (type))
- pedwarn (input_location, OPT_pedantic, "ISO C++ forbids initialization of member constant "
+ pedwarn (input_location, OPT_Wpedantic, "ISO C++ forbids initialization of member constant "
"%qD of non-integral type %qT", decl, type);
return 0;
else if (in_system_header)
/* Allow them in system headers because glibc uses them. */;
else if (name)
- pedwarn (input_location, OPT_pedantic, "ISO C++ forbids zero-size array %qD", name);
+ pedwarn (input_location, OPT_Wpedantic, "ISO C++ forbids zero-size array %qD", name);
else
- pedwarn (input_location, OPT_pedantic, "ISO C++ forbids zero-size array");
+ pedwarn (input_location, OPT_Wpedantic, "ISO C++ forbids zero-size array");
}
}
else if (TREE_CONSTANT (size)
/* 8.3.4/1: If the type of the identifier of D contains the auto
type-specifier, the program is ill-formed. */
if (pedantic && type_uses_auto (type))
- pedwarn (input_location, OPT_pedantic,
+ pedwarn (input_location, OPT_Wpedantic,
"declaration of %qD as array of %<auto%>", name);
/* If there are some types which cannot be array elements,
bool parameter_pack_p = declarator? declarator->parameter_pack_p : false;
bool template_type_arg = false;
bool template_parm_flag = false;
- bool constexpr_p = declspecs->specs[(int) ds_constexpr];
+ bool constexpr_p = decl_spec_seq_has_spec_p (declspecs, ds_constexpr);
const char *errmsg;
- signed_p = declspecs->specs[(int)ds_signed];
- unsigned_p = declspecs->specs[(int)ds_unsigned];
- short_p = declspecs->specs[(int)ds_short];
- long_p = declspecs->specs[(int)ds_long];
- longlong = declspecs->specs[(int)ds_long] >= 2;
+ signed_p = decl_spec_seq_has_spec_p (declspecs, ds_signed);
+ unsigned_p = decl_spec_seq_has_spec_p (declspecs, ds_unsigned);
+ short_p = decl_spec_seq_has_spec_p (declspecs, ds_short);
+ long_p = decl_spec_seq_has_spec_p (declspecs, ds_long);
+ longlong = decl_spec_seq_has_spec_p (declspecs, ds_long_long);
explicit_int128 = declspecs->explicit_int128_p;
- thread_p = declspecs->specs[(int)ds_thread];
+ thread_p = decl_spec_seq_has_spec_p (declspecs, ds_thread);
if (decl_context == FUNCDEF)
funcdef_flag = true, decl_context = NORMAL;
if (dname && IDENTIFIER_OPNAME_P (dname))
{
- if (declspecs->specs[(int)ds_typedef])
+ if (decl_spec_seq_has_spec_p (declspecs, ds_typedef))
{
error ("declaration of %qD as %<typedef%>", dname);
return error_mark_node;
if (name == NULL)
name = decl_context == PARM ? "parameter" : "type name";
- if (constexpr_p && declspecs->specs[(int)ds_typedef])
+ if (constexpr_p && decl_spec_seq_has_spec_p (declspecs, ds_typedef))
{
error ("%<constexpr%> cannot appear in a typedef declaration");
return error_mark_node;
else if (! is_main)
permerror (input_location, "ISO C++ forbids declaration of %qs with no type", name);
else if (pedantic)
- pedwarn (input_location, OPT_pedantic,
+ pedwarn (input_location, OPT_Wpedantic,
"ISO C++ forbids declaration of %qs with no type", name);
else
warning (OPT_Wreturn_type,
explicit_int128 = false;
}
else if (pedantic && ! in_system_header)
- pedwarn (input_location, OPT_pedantic,
+ pedwarn (input_location, OPT_Wpedantic,
"ISO C++ does not support %<__int128%> for %qs", name);
}
ok = 1;
if (!explicit_int && !defaulted_int && !explicit_char && !explicit_int128 && pedantic)
{
- pedwarn (input_location, OPT_pedantic,
+ pedwarn (input_location, OPT_Wpedantic,
"long, short, signed or unsigned used invalidly for %qs",
name);
if (flag_pedantic_errors)
else if (short_p)
type = short_integer_type_node;
- if (declspecs->specs[(int)ds_complex])
+ 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);
}
type_quals = TYPE_UNQUALIFIED;
- if (declspecs->specs[(int)ds_const])
+ if (decl_spec_seq_has_spec_p (declspecs, ds_const))
type_quals |= TYPE_QUAL_CONST;
- if (declspecs->specs[(int)ds_volatile])
+ if (decl_spec_seq_has_spec_p (declspecs, ds_volatile))
type_quals |= TYPE_QUAL_VOLATILE;
- if (declspecs->specs[(int)ds_restrict])
+ if (decl_spec_seq_has_spec_p (declspecs, ds_restrict))
type_quals |= TYPE_QUAL_RESTRICT;
if (sfk == sfk_conversion && type_quals != TYPE_UNQUALIFIED)
error ("qualifiers are not allowed on declaration of %<operator %T%>",
ctor_return_type);
+ /* If we're using the injected-class-name to form a compound type or a
+ declaration, replace it with the underlying class so we don't get
+ redundant typedefs in the debug output. But if we are returning the
+ type unchanged, leave it alone so that it's available to
+ maybe_get_template_decl_from_type_decl. */
+ if (CLASS_TYPE_P (type)
+ && DECL_SELF_REFERENCE_P (TYPE_NAME (type))
+ && type == TREE_TYPE (TYPE_NAME (type))
+ && (declarator || type_quals))
+ type = DECL_ORIGINAL_TYPE (TYPE_NAME (type));
+
type_quals |= cp_type_quals (type);
type = cp_build_qualified_type_real
(type, type_quals, ((typedef_decl && !DECL_ARTIFICIAL (typedef_decl)
type_quals = cp_type_quals (type);
staticp = 0;
- inlinep = !! declspecs->specs[(int)ds_inline];
- virtualp = !! declspecs->specs[(int)ds_virtual];
- explicitp = !! declspecs->specs[(int)ds_explicit];
+ inlinep = decl_spec_seq_has_spec_p (declspecs, ds_inline);
+ virtualp = decl_spec_seq_has_spec_p (declspecs, ds_virtual);
+ explicitp = decl_spec_seq_has_spec_p (declspecs, ds_explicit);
storage_class = declspecs->storage_class;
if (storage_class == sc_static)
storage_class = sc_none;
staticp = 0;
}
- friendp = !! declspecs->specs[(int)ds_friend];
+ friendp = decl_spec_seq_has_spec_p (declspecs, ds_friend);
if (dependent_name && !friendp)
{
/* Issue errors about use of storage classes for parameters. */
if (decl_context == PARM)
{
- if (declspecs->specs[(int)ds_typedef])
+ if (decl_spec_seq_has_spec_p (declspecs, ds_typedef))
{
error ("typedef declaration invalid in parameter declaration");
return error_mark_node;
&& ((storage_class
&& storage_class != sc_extern
&& storage_class != sc_static)
- || declspecs->specs[(int)ds_typedef]))
+ || decl_spec_seq_has_spec_p (declspecs, ds_typedef)))
{
error ("multiple storage classes in declaration of %qs", name);
thread_p = false;
&& (storage_class == sc_register
|| storage_class == sc_auto))
;
- else if (declspecs->specs[(int)ds_typedef])
+ else if (decl_spec_seq_has_spec_p (declspecs, ds_typedef))
;
else if (decl_context == FIELD
/* C++ allows static class elements. */
error ("%qs declared as function returning an array", name);
return error_mark_node;
}
+ /* When decl_context == NORMAL we emit a better error message
+ later in abstract_virtuals_error. */
+ if (decl_context == TYPENAME && ABSTRACT_CLASS_TYPE_P (type))
+ error ("%qs declared as function returning an abstract "
+ "class type", name);
/* Pick up type qualifiers which should be applied to `this'. */
memfn_quals = declarator->u.function.qualifiers;
{
if (!declarator->u.function.late_return_type)
{
- error ("%qs function uses %<auto%> type specifier without"
- " trailing return type", name);
- return error_mark_node;
+ if (current_class_type
+ && LAMBDA_TYPE_P (current_class_type))
+ /* OK for C++11 lambdas. */;
+ else if (cxx_dialect < cxx1y)
+ pedwarn (input_location, 0, "%qs function uses "
+ "%<auto%> type specifier without trailing "
+ "return type", name);
}
else if (!is_auto (type))
{
return error_mark_node;
}
}
- else if (declspecs->specs[(int)ds_typedef]
+ else if (decl_spec_seq_has_spec_p (declspecs, ds_typedef)
&& current_class_type)
{
error ("cannot declare member %<%T::%s%> within %qT",
error ("non-parameter %qs cannot be a parameter pack", name);
}
- /* Did array size calculations overflow? */
-
+ /* Did array size calculations overflow or does the array cover more
+ than half of the address-space? */
if (TREE_CODE (type) == ARRAY_TYPE
&& COMPLETE_TYPE_P (type)
&& TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST
- && TREE_OVERFLOW (TYPE_SIZE_UNIT (type)))
+ && ! valid_constant_size_p (TYPE_SIZE_UNIT (type)))
{
error ("size of array %qs is too large", name);
/* If we proceed with the array type as it is, we'll eventually
error ("non-member %qs cannot be declared %<mutable%>", name);
storage_class = sc_none;
}
- else if (decl_context == TYPENAME || declspecs->specs[(int)ds_typedef])
+ else if (decl_context == TYPENAME
+ || decl_spec_seq_has_spec_p (declspecs, ds_typedef))
{
error ("non-object member %qs cannot be declared %<mutable%>", name);
storage_class = sc_none;
}
/* If this is declaring a typedef name, return a TYPE_DECL. */
- if (declspecs->specs[(int)ds_typedef] && decl_context != TYPENAME)
+ if (decl_spec_seq_has_spec_p (declspecs, ds_typedef) && decl_context != TYPENAME)
{
tree decl;
memfn_quals != TYPE_UNQUALIFIED,
inlinep, friendp, raises != NULL_TREE);
- if (declspecs->specs[(int)ds_alias])
+ if (decl_spec_seq_has_spec_p (declspecs, ds_alias))
/* Acknowledge that this was written:
`using analias = atype;'. */
TYPE_DECL_ALIAS_P (decl) = 1;
}
else if (decl_context == FIELD)
{
- if (!staticp && type_uses_auto (type))
+ if (!staticp && TREE_CODE (type) != METHOD_TYPE
+ && type_uses_auto (type))
{
error ("non-static data member declared %<auto%>");
type = error_mark_node;
{
/* C++ allows static class members. All other work
for this is done by grokfield. */
- decl = build_lang_decl (VAR_DECL, unqualified_id, type);
+ decl = build_lang_decl_loc (declarator->id_loc,
+ VAR_DECL, unqualified_id, type);
set_linkage_for_static_data_member (decl);
/* Even if there is an in-class initialization, DECL
is considered undefined until an out-of-class
and `extern' makes no difference. */
if (! toplevel_bindings_p ()
&& (storage_class == sc_static
- || declspecs->specs[(int)ds_inline])
+ || decl_spec_seq_has_spec_p (declspecs, ds_inline))
&& pedantic)
{
if (storage_class == sc_static)
- pedwarn (input_location, OPT_pedantic,
+ pedwarn (input_location, OPT_Wpedantic,
"%<static%> specified invalid for function %qs "
"declared out of global scope", name);
else
- pedwarn (input_location, OPT_pedantic,
+ pedwarn (input_location, OPT_Wpedantic,
"%<inline%> specifier invalid for function %qs "
"declared out of global scope", name);
}
}
if (storage_class == sc_extern && pedantic)
{
- pedwarn (input_location, OPT_pedantic,
+ pedwarn (input_location, OPT_Wpedantic,
"cannot explicitly declare member %q#D to have "
"extern linkage", decl);
storage_class = sc_none;
A default argument expression is implicitly converted to the
parameter type. */
if (!TREE_TYPE (arg)
- || !can_convert_arg (decl_type, TREE_TYPE (arg), arg, LOOKUP_NORMAL))
+ || !can_convert_arg (decl_type, TREE_TYPE (arg), arg, LOOKUP_NORMAL,
+ tf_warning_or_error))
{
if (decl)
error ("default argument for %q#D has type %qT",
return error_mark_node;
}
+ if (warn_zero_as_null_pointer_constant
+ && c_inhibit_evaluation_warnings == 0
+ && TYPE_PTR_OR_PTRMEM_P (decl_type)
+ && null_ptr_cst_p (arg)
+ && !NULLPTR_TYPE_P (TREE_TYPE (arg)))
+ {
+ warning (OPT_Wzero_as_null_pointer_constant,
+ "zero as null pointer constant");
+ return nullptr_node;
+ }
+
/* [dcl.fct.default]
Local variables shall not be used in default argument
if (operator_code == POSTINCREMENT_EXPR
|| operator_code == POSTDECREMENT_EXPR)
{
- pedwarn (input_location, OPT_pedantic, "%qD cannot have default arguments",
+ pedwarn (input_location, OPT_Wpedantic, "%qD cannot have default arguments",
decl);
}
else
/* In a function definition, arg types must be complete. */
require_complete_types_for_parms (current_function_parms);
- if (dependent_type_p (return_type))
+ if (dependent_type_p (return_type)
+ || type_uses_auto (return_type))
return;
if (!COMPLETE_OR_VOID_TYPE_P (return_type)
|| (TYPE_FOR_JAVA (return_type) && MAYBE_CLASS_TYPE_P (return_type)))
/* Build the return declaration for the function. */
restype = TREE_TYPE (fntype);
+
if (DECL_RESULT (decl1) == NULL_TREE)
{
tree resdecl;
current_stmt_tree ()->stmts_are_full_exprs_p = 1;
current_binding_level = bl;
+ if (!processing_template_decl && type_uses_auto (restype))
+ {
+ FNDECL_USED_AUTO (decl1) = true;
+ current_function_auto_return_pattern = restype;
+ }
+
/* Start the statement-tree, start the tree now. */
DECL_SAVED_TREE (decl1) = push_stmt_list ();
of curly braces for a function. */
gcc_assert (stmts_are_full_exprs_p ());
+ /* If there are no return statements in a function with auto return type,
+ 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)
+ {
+ if (!is_auto (current_function_auto_return_pattern)
+ && !current_function_returns_value && !current_function_returns_null)
+ {
+ error ("no return statements in function returning %qT",
+ current_function_auto_return_pattern);
+ inform (input_location, "only plain %<auto%> return type can be "
+ "deduced to %<void%>");
+ }
+ apply_deduced_return_type (fndecl, void_type_node);
+ fntype = TREE_TYPE (fndecl);
+ }
+
/* Save constexpr function body before it gets munged by
the NRV transformation. */
maybe_save_function_definition (fndecl);