/* Process declarations and variables for C++ compiler.
- Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
- Free Software Foundation, Inc.
+ Copyright (C) 1988-2013 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GCC.
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
+#include "stringpool.h"
+#include "stor-layout.h"
+#include "varasm.h"
+#include "attribs.h"
+#include "calls.h"
#include "flags.h"
#include "cp-tree.h"
#include "tree-iterator.h"
#include "c-family/c-common.h"
#include "c-family/c-objc.h"
#include "c-family/c-pragma.h"
+#include "c-family/c-target.h"
+#include "c-family/c-ubsan.h"
#include "diagnostic.h"
#include "intl.h"
#include "debug.h"
#include "splay-tree.h"
#include "plugin.h"
#include "cgraph.h"
+#include "wide-int.h"
/* Possible cases of bad specifiers type used by bad_specifiers. */
enum bad_spec_place {
static int check_static_variable_definition (tree, tree);
static void record_unknown_type (tree, const char *);
static tree builtin_function_1 (tree, tree, bool);
-static tree build_library_fn_1 (tree, enum tree_code, tree);
static int member_function_or_else (tree, tree, enum overload_flags);
static void bad_specifiers (tree, enum bad_spec_place, int, int, int, int,
int);
static void initialize_predefined_identifiers (void);
static tree check_special_function_return_type
(special_function_kind, tree, tree);
-static tree push_cp_library_fn (enum tree_code, tree);
-static tree build_cp_library_fn (tree, enum tree_code, tree);
+static tree push_cp_library_fn (enum tree_code, tree, int);
+static tree build_cp_library_fn (tree, enum tree_code, tree, int);
static void store_parm_decls (tree);
static void initialize_local_var (tree, tree);
static void expand_static_init (tree, tree);
push_local_binding where the list of decls returned by
getdecls is built. */
decl = TREE_CODE (d) == TREE_LIST ? TREE_VALUE (d) : d;
- if (TREE_CODE (decl) == VAR_DECL
+ // See through references for improved -Wunused-variable (PR 38958).
+ tree type = non_reference (TREE_TYPE (decl));
+ if (VAR_P (decl)
&& (! TREE_USED (decl) || !DECL_READ_P (decl))
&& ! DECL_IN_SYSTEM_HEADER (decl)
&& DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl)
- && TREE_TYPE (decl) != error_mark_node
- && (!CLASS_TYPE_P (TREE_TYPE (decl))
- || !TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (decl))))
+ && type != error_mark_node
+ && (!CLASS_TYPE_P (type)
+ || !TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
+ || lookup_attribute ("warn_unused",
+ TYPE_ATTRIBUTES (TREE_TYPE (decl)))))
{
if (! TREE_USED (decl))
warning (OPT_Wunused_variable, "unused variable %q+D", decl);
else if (DECL_CONTEXT (decl) == current_function_decl
+ // For -Wunused-but-set-variable leave references alone.
&& TREE_CODE (TREE_TYPE (decl)) != REFERENCE_TYPE
&& errorcount == unused_but_set_errorcount)
{
/* Remove declarations for all the DECLs in this level. */
for (link = decls; link; link = TREE_CHAIN (link))
{
- if (leaving_for_scope && TREE_CODE (link) == VAR_DECL
+ if (leaving_for_scope && VAR_P (link)
/* It's hard to make this ARM compatibility hack play nicely with
lambdas, and it really isn't necessary in C++11 mode. */
- && cxx_dialect < cxx0x
+ && cxx_dialect < cxx11
&& DECL_NAME (link))
{
tree name = DECL_NAME (link);
if (!DECL_LANG_SPECIFIC (decl))
retrofit_lang_decl (decl);
DECL_LANG_SPECIFIC (decl)->u.base.u2sel = 1;
- if (DECL_LANG_SPECIFIC (t))
+ if (DECL_DISCRIMINATOR_SET_P (t))
DECL_DISCRIMINATOR (decl) = DECL_DISCRIMINATOR (t) + 1;
else
DECL_DISCRIMINATOR (decl) = 1;
if (t1 != t2)
return 0;
- /* The decls dont match if they correspond to two different versions
- of the same function. Disallow extern "C" functions to be
- versions for now. */
- if (compparms (p1, p2)
- && same_type_p (TREE_TYPE (f1), TREE_TYPE (f2))
- && !DECL_EXTERN_C_P (newdecl)
- && !DECL_EXTERN_C_P (olddecl)
- && targetm.target_option.function_versions (newdecl, olddecl))
- {
- /* Mark functions as versions if necessary. Modify the mangled decl
- name if necessary. */
- if (DECL_FUNCTION_VERSIONED (newdecl)
- && DECL_FUNCTION_VERSIONED (olddecl))
- return 0;
- if (!DECL_FUNCTION_VERSIONED (newdecl))
- {
- DECL_FUNCTION_VERSIONED (newdecl) = 1;
- if (DECL_ASSEMBLER_NAME_SET_P (newdecl))
- mangle_decl (newdecl);
- }
- if (!DECL_FUNCTION_VERSIONED (olddecl))
- {
- DECL_FUNCTION_VERSIONED (olddecl) = 1;
- if (DECL_ASSEMBLER_NAME_SET_P (olddecl))
- mangle_decl (olddecl);
- }
- record_function_versions (olddecl, newdecl);
- return 0;
- }
-
if (CP_DECL_CONTEXT (newdecl) != CP_DECL_CONTEXT (olddecl)
&& ! (DECL_EXTERN_C_P (newdecl)
&& DECL_EXTERN_C_P (olddecl)))
/* 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);
+ r2 = fndecl_declared_return_type (olddecl);
if (same_type_p (TREE_TYPE (f1), r2))
{
else
types_match =
compparms (p1, p2)
+ && type_memfn_rqual (f1) == type_memfn_rqual (f2)
&& (TYPE_ATTRIBUTES (TREE_TYPE (newdecl)) == NULL_TREE
|| comp_type_attributes (TREE_TYPE (newdecl),
TREE_TYPE (olddecl)) != 0);
}
else
types_match = 0;
+
+ /* The decls dont match if they correspond to two different versions
+ of the same function. Disallow extern "C" functions to be
+ versions for now. */
+ if (types_match
+ && !DECL_EXTERN_C_P (newdecl)
+ && !DECL_EXTERN_C_P (olddecl)
+ && targetm.target_option.function_versions (newdecl, olddecl))
+ {
+ /* Mark functions as versions if necessary. Modify the mangled decl
+ name if necessary. */
+ if (DECL_FUNCTION_VERSIONED (newdecl)
+ && DECL_FUNCTION_VERSIONED (olddecl))
+ return 0;
+ if (!DECL_FUNCTION_VERSIONED (newdecl))
+ {
+ DECL_FUNCTION_VERSIONED (newdecl) = 1;
+ if (DECL_ASSEMBLER_NAME_SET_P (newdecl))
+ mangle_decl (newdecl);
+ }
+ if (!DECL_FUNCTION_VERSIONED (olddecl))
+ {
+ DECL_FUNCTION_VERSIONED (olddecl) = 1;
+ if (DECL_ASSEMBLER_NAME_SET_P (olddecl))
+ mangle_decl (olddecl);
+ }
+ record_function_versions (olddecl, newdecl);
+ return 0;
+ }
}
else if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
{
/* Need to check scope for variable declaration (VAR_DECL).
For typedef (TYPE_DECL), scope is ignored. */
- if (TREE_CODE (newdecl) == VAR_DECL
+ if (VAR_P (newdecl)
&& CP_DECL_CONTEXT (newdecl) != CP_DECL_CONTEXT (olddecl)
/* [dcl.link]
Two declarations for an object with C language linkage
&& DECL_ARTIFICIAL (olddecl))
return;
- permerror (input_location, "%qD was declared %<extern%> and later %<static%>", newdecl);
- permerror (input_location, "previous declaration of %q+D", olddecl);
+ if (permerror (input_location,
+ "%qD was declared %<extern%> and later %<static%>", newdecl))
+ inform (input_location, "previous declaration of %q+D", olddecl);
}
/* NEW_DECL is a redeclaration of OLD_DECL; both are functions or
if (DECL_DECLARED_CONSTEXPR_P (old_decl)
== DECL_DECLARED_CONSTEXPR_P (new_decl))
return true;
- if (TREE_CODE (old_decl) == FUNCTION_DECL && DECL_BUILT_IN (old_decl))
+ if (TREE_CODE (old_decl) == FUNCTION_DECL)
{
- /* Hide a built-in declaration. */
- DECL_DECLARED_CONSTEXPR_P (old_decl)
- = DECL_DECLARED_CONSTEXPR_P (new_decl);
- return true;
+ if (DECL_BUILT_IN (old_decl))
+ {
+ /* Hide a built-in declaration. */
+ DECL_DECLARED_CONSTEXPR_P (old_decl)
+ = DECL_DECLARED_CONSTEXPR_P (new_decl);
+ return true;
+ }
+ /* 7.1.5 [dcl.constexpr]
+ Note: An explicit specialization can differ from the template
+ declaration with respect to the constexpr specifier. */
+ if (! DECL_TEMPLATE_SPECIALIZATION (old_decl)
+ && DECL_TEMPLATE_SPECIALIZATION (new_decl))
+ return true;
+
+ error ("redeclaration %qD differs in %<constexpr%>", new_decl);
+ error ("from previous declaration %q+D", old_decl);
+ return false;
}
- error ("redeclaration %qD differs in %<constexpr%>", new_decl);
- error ("from previous declaration %q+D", old_decl);
- return false;
+ return true;
}
#define GNU_INLINE_P(fn) (DECL_DECLARED_INLINE_P (fn) \
&& DECL_UNINLINABLE (olddecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
{
- warning (OPT_Wattributes, "function %q+D redeclared as inline",
- newdecl);
- warning (OPT_Wattributes, "previous declaration of %q+D "
- "with attribute noinline", olddecl);
+ if (warning (OPT_Wattributes, "function %q+D redeclared as inline",
+ newdecl))
+ inform (input_location, "previous declaration of %q+D "
+ "with attribute noinline", olddecl);
}
else if (DECL_DECLARED_INLINE_P (olddecl)
&& DECL_UNINLINABLE (newdecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
{
- warning (OPT_Wattributes, "function %q+D redeclared with "
- "attribute noinline", newdecl);
- warning (OPT_Wattributes, "previous declaration of %q+D was inline",
- olddecl);
+ if (warning (OPT_Wattributes, "function %q+D redeclared with "
+ "attribute noinline", newdecl))
+ inform (input_location, "previous declaration of %q+D was inline",
+ olddecl);
}
}
}
return NULL_TREE;
}
+ else if (DECL_OMP_DECLARE_REDUCTION_P (olddecl))
+ {
+ gcc_assert (DECL_OMP_DECLARE_REDUCTION_P (newdecl));
+ error_at (DECL_SOURCE_LOCATION (newdecl),
+ "redeclaration of %<pragma omp declare reduction%>");
+ error_at (DECL_SOURCE_LOCATION (olddecl),
+ "previous %<pragma omp declare reduction%> declaration");
+ return error_mark_node;
+ }
else if (!types_match)
{
/* Avoid warnings redeclaring built-ins which have not been
{
tree t = TREE_VALUE (t1);
- if (TREE_CODE (t) == POINTER_TYPE
+ if (TYPE_PTR_P (t)
&& TYPE_NAME (TREE_TYPE (t))
&& DECL_NAME (TYPE_NAME (TREE_TYPE (t)))
== get_identifier ("FILE")
error ("%q#D redeclared as different kind of symbol", newdecl);
if (TREE_CODE (olddecl) == TREE_LIST)
olddecl = TREE_VALUE (olddecl);
- error ("previous declaration of %q+#D", olddecl);
+ inform (input_location, "previous declaration of %q+#D", olddecl);
return error_mark_node;
}
TYPE_ARG_TYPES (TREE_TYPE (olddecl))))
{
error ("new declaration %q#D", newdecl);
- 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);
+ error ("ambiguates old declaration %q+#D", olddecl);
return error_mark_node;
}
else
else
{
error ("conflicting declaration %q#D", newdecl);
- error ("%q+D has a previous declaration as %q#D", olddecl, olddecl);
+ inform (input_location,
+ "%q+D has a previous declaration as %q#D", olddecl, olddecl);
return error_mark_node;
}
}
{
error_at (DECL_SOURCE_LOCATION (newdecl), errmsg, newdecl);
if (DECL_NAME (olddecl) != NULL_TREE)
- error ((DECL_INITIAL (olddecl) && namespace_bindings_p ())
- ? G_("%q+#D previously defined here")
- : G_("%q+#D previously declared here"), olddecl);
+ inform (input_location,
+ (DECL_INITIAL (olddecl) && namespace_bindings_p ())
+ ? G_("%q+#D previously defined here")
+ : G_("%q+#D previously declared here"), olddecl);
return error_mark_node;
}
else if (TREE_CODE (olddecl) == FUNCTION_DECL
warning_at (DECL_SOURCE_LOCATION (olddecl), 0,
"follows non-prototype definition here");
}
- else if ((TREE_CODE (olddecl) == FUNCTION_DECL
- || TREE_CODE (olddecl) == VAR_DECL)
+ else if (VAR_OR_FUNCTION_DECL_P (olddecl)
&& DECL_LANGUAGE (newdecl) != DECL_LANGUAGE (olddecl))
{
/* [dcl.link]
&& (! DECL_TEMPLATE_SPECIALIZATION (newdecl)
|| DECL_TEMPLATE_SPECIALIZATION (olddecl)))
{
- warning (OPT_Wredundant_decls, "redundant redeclaration of %qD in same scope", newdecl);
- warning (OPT_Wredundant_decls, "previous declaration of %q+D", olddecl);
+ if (warning (OPT_Wredundant_decls,
+ "redundant redeclaration of %qD in same scope",
+ newdecl))
+ inform (input_location, "previous declaration of %q+D", olddecl);
}
- if (DECL_DELETED_FN (newdecl))
+ if (!(DECL_TEMPLATE_INSTANTIATION (olddecl)
+ && DECL_TEMPLATE_SPECIALIZATION (newdecl)))
{
- error ("deleted definition of %qD", newdecl);
- error ("after previous declaration %q+D", olddecl);
+ if (DECL_DELETED_FN (newdecl))
+ {
+ error ("deleted definition of %qD", newdecl);
+ error ("after previous declaration %q+D", olddecl);
+ }
+ DECL_DELETED_FN (newdecl) |= DECL_DELETED_FN (olddecl);
}
- DECL_DELETED_FN (newdecl) |= DECL_DELETED_FN (olddecl);
}
/* Deal with C++: must preserve virtual function table size. */
&& newtype == DECL_ORIGINAL_TYPE (newdecl))
newtype = oldtype;
- if (TREE_CODE (newdecl) == VAR_DECL)
+ if (VAR_P (newdecl))
{
DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl);
DECL_INITIALIZED_P (newdecl) |= DECL_INITIALIZED_P (olddecl);
&& !(processing_template_decl && uses_template_parms (newdecl)))
layout_type (TREE_TYPE (newdecl));
- if ((TREE_CODE (newdecl) == VAR_DECL
+ if ((VAR_P (newdecl)
|| TREE_CODE (newdecl) == PARM_DECL
|| TREE_CODE (newdecl) == RESULT_DECL
|| TREE_CODE (newdecl) == FIELD_DECL
/* Keep the old RTL. */
COPY_DECL_RTL (olddecl, newdecl);
}
- else if (TREE_CODE (newdecl) == VAR_DECL
+ else if (VAR_P (newdecl)
&& (DECL_SIZE (olddecl) || !DECL_SIZE (newdecl)))
{
/* Keep the old RTL. We cannot keep the old RTL if the old
DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
}
/* Only functions have these fields. */
- if (TREE_CODE (newdecl) == FUNCTION_DECL
- || DECL_FUNCTION_TEMPLATE_P (newdecl))
+ if (DECL_DECLARES_FUNCTION_P (newdecl))
{
DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
olddecl_friend = DECL_FRIEND_P (olddecl);
SET_DECL_THUNKS (newdecl, DECL_THUNKS (olddecl));
}
/* Only variables have this field. */
- else if (TREE_CODE (newdecl) == VAR_DECL
+ else if (VAR_P (newdecl)
&& VAR_HAD_UNKNOWN_BOUND (olddecl))
SET_VAR_HAD_UNKNOWN_BOUND (newdecl);
}
}
/* Init priority used to be merged from newdecl to olddecl by the memcpy,
so keep this behavior. */
- if (TREE_CODE (newdecl) == VAR_DECL && DECL_HAS_INIT_PRIORITY_P (newdecl))
+ if (VAR_P (newdecl) && DECL_HAS_INIT_PRIORITY_P (newdecl))
{
SET_DECL_INIT_PRIORITY (olddecl, DECL_INIT_PRIORITY (newdecl));
DECL_HAS_INIT_PRIORITY_P (olddecl) = 1;
TREE_USED (newdecl) = 1;
else if (TREE_USED (newdecl))
TREE_USED (olddecl) = 1;
- if (TREE_CODE (newdecl) == VAR_DECL)
+ if (VAR_P (newdecl))
{
if (DECL_READ_P (olddecl))
DECL_READ_P (newdecl) = 1;
flags and attributes. */
if (DECL_RTL_SET_P (olddecl)
&& (TREE_CODE (olddecl) == FUNCTION_DECL
- || (TREE_CODE (olddecl) == VAR_DECL
+ || (VAR_P (olddecl)
&& TREE_STATIC (olddecl))))
make_decl_rtl (olddecl);
return NULL;
}
- else if (TREE_CODE (newdecl) == VAR_DECL
+ else if (VAR_P (newdecl)
&& DECL_THREAD_LOCAL_P (newdecl) != DECL_THREAD_LOCAL_P (olddecl)
&& (! DECL_LANG_SPECIFIC (olddecl)
|| ! CP_DECL_THREADPRIVATE_P (olddecl)
union { int i; };
is invalid. */
- if ((TREE_CODE (newdecl) == VAR_DECL && DECL_ANON_UNION_VAR_P (newdecl))
- || (TREE_CODE (olddecl) == VAR_DECL && DECL_ANON_UNION_VAR_P (olddecl)))
+ if ((VAR_P (newdecl) && DECL_ANON_UNION_VAR_P (newdecl))
+ || (VAR_P (olddecl) && DECL_ANON_UNION_VAR_P (olddecl)))
return G_("redeclaration of %q#D");
/* If at least one declaration is a reference, there is no
conflict. For example:
preceding types and is declared without an initializer (8.5). */
tree type = TREE_TYPE (decl);
- if (TREE_CODE (decl) != VAR_DECL || TREE_STATIC (decl)
+ if (!VAR_P (decl) || TREE_STATIC (decl)
|| type == error_mark_node)
return 0;
if (value == NULL_TREE)
return value;
- if (cxx_dialect >= cxx0x
+ 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 (type, value, tf_warning_or_error);
+ value = (perform_implicit_conversion_flags
+ (type, value, tf_warning_or_error,
+ LOOKUP_IMPLICIT | LOOKUP_NO_NON_INTEGRAL));
}
return cxx_constant_value (value);
}
error ("%qD used without template parameters", name);
return error_mark_node;
}
- gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
+ gcc_assert (identifier_p (name));
gcc_assert (TYPE_P (context));
if (!MAYBE_CLASS_TYPE_P (context))
name = TYPE_IDENTIFIER (name);
else if (DECL_P (name))
name = DECL_NAME (name);
- gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
+ gcc_assert (identifier_p (name));
if (!dependent_type_p (context)
|| currently_open_class (context))
newtype = build_exception_variant (newtype, new_eh_spec);
deltype = cp_build_type_attribute_variant (void_ftype_ptr, extvisattr);
deltype = build_exception_variant (deltype, empty_except_spec);
- push_cp_library_fn (NEW_EXPR, newtype);
- push_cp_library_fn (VEC_NEW_EXPR, newtype);
- global_delete_fndecl = push_cp_library_fn (DELETE_EXPR, deltype);
- push_cp_library_fn (VEC_DELETE_EXPR, deltype);
+ DECL_IS_OPERATOR_NEW (push_cp_library_fn (NEW_EXPR, newtype, 0)) = 1;
+ DECL_IS_OPERATOR_NEW (push_cp_library_fn (VEC_NEW_EXPR, newtype, 0)) = 1;
+ global_delete_fndecl = push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW);
+ push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW);
nullptr_type_node = make_node (NULLPTR_TYPE);
TYPE_SIZE (nullptr_type_node) = bitsize_int (GET_MODE_BITSIZE (ptr_mode));
}
abort_fndecl
- = build_library_fn_ptr ("__cxa_pure_virtual", void_ftype);
+ = build_library_fn_ptr ("__cxa_pure_virtual", void_ftype,
+ ECF_NORETURN | ECF_NOTHROW);
/* Perform other language dependent initializations. */
init_class_processing ();
function. Not called directly. */
static tree
-build_library_fn_1 (tree name, enum tree_code operator_code, tree type)
+build_library_fn (tree name, enum tree_code operator_code, tree type,
+ int ecf_flags)
{
tree fn = build_lang_decl (FUNCTION_DECL, name, type);
DECL_EXTERNAL (fn) = 1;
external shared object. */
DECL_VISIBILITY (fn) = VISIBILITY_DEFAULT;
DECL_VISIBILITY_SPECIFIED (fn) = 1;
- return fn;
-}
-
-/* Returns the _DECL for a library function with C linkage.
- We assume that such functions never throw; if this is incorrect,
- callers should unset TREE_NOTHROW. */
-
-static tree
-build_library_fn (tree name, tree type)
-{
- tree fn = build_library_fn_1 (name, ERROR_MARK, type);
- TREE_NOTHROW (fn) = 1;
+ set_call_expr_flags (fn, ecf_flags);
return fn;
}
/* Returns the _DECL for a library function with C++ linkage. */
static tree
-build_cp_library_fn (tree name, enum tree_code operator_code, tree type)
+build_cp_library_fn (tree name, enum tree_code operator_code, tree type,
+ int ecf_flags)
{
- tree fn = build_library_fn_1 (name, operator_code, type);
- TREE_NOTHROW (fn) = TYPE_NOTHROW_P (type);
+ tree fn = build_library_fn (name, operator_code, type, ecf_flags);
DECL_CONTEXT (fn) = FROB_CONTEXT (current_namespace);
SET_DECL_LANGUAGE (fn, lang_cplusplus);
return fn;
IDENTIFIER_NODE. */
tree
-build_library_fn_ptr (const char* name, tree type)
+build_library_fn_ptr (const char* name, tree type, int ecf_flags)
{
- return build_library_fn (get_identifier (name), type);
+ return build_library_fn (get_identifier (name), ERROR_MARK, type, ecf_flags);
}
/* Like build_cp_library_fn, but takes a C string instead of an
IDENTIFIER_NODE. */
tree
-build_cp_library_fn_ptr (const char* name, tree type)
+build_cp_library_fn_ptr (const char* name, tree type, int ecf_flags)
{
- return build_cp_library_fn (get_identifier (name), ERROR_MARK, type);
+ return build_cp_library_fn (get_identifier (name), ERROR_MARK, type,
+ ecf_flags);
}
/* Like build_library_fn, but also pushes the function so that we will
may throw exceptions listed in RAISES. */
tree
-push_library_fn (tree name, tree type, tree raises)
+push_library_fn (tree name, tree type, tree raises, int ecf_flags)
{
tree fn;
if (raises)
type = build_exception_variant (type, raises);
- fn = build_library_fn (name, type);
+ fn = build_library_fn (name, ERROR_MARK, type, ecf_flags);
pushdecl_top_level (fn);
return fn;
}
will be found by normal lookup. */
static tree
-push_cp_library_fn (enum tree_code operator_code, tree type)
+push_cp_library_fn (enum tree_code operator_code, tree type,
+ int ecf_flags)
{
tree fn = build_cp_library_fn (ansi_opname (operator_code),
operator_code,
- type);
+ type, ecf_flags);
pushdecl (fn);
if (flag_tm)
apply_tm_attr (fn, get_identifier ("transaction_safe"));
a FUNCTION_TYPE. */
tree
-push_void_library_fn (tree name, tree parmtypes)
+push_void_library_fn (tree name, tree parmtypes, int ecf_flags)
{
tree type = build_function_type (void_type_node, parmtypes);
- return push_library_fn (name, type, NULL_TREE);
+ return push_library_fn (name, type, NULL_TREE, ecf_flags);
}
/* Like push_library_fn, but also note that this function throws
tree
push_throw_library_fn (tree name, tree type)
{
- tree fn = push_library_fn (name, type, NULL_TREE);
- TREE_THIS_VOLATILE (fn) = 1;
- TREE_NOTHROW (fn) = 0;
+ tree fn = push_library_fn (name, type, NULL_TREE, ECF_NORETURN);
return fn;
}
\f
warn_misplaced_attr_for_class_type (source_location location,
tree class_type)
{
- gcc_assert (TAGGED_TYPE_P (class_type));
+ gcc_assert (OVERLOAD_TYPE_P (class_type));
warning_at (location, OPT_Wattributes,
"attribute ignored in declaration "
deprecated_state = DEPRECATED_NORMAL;
- if (decl == NULL_TREE || TREE_CODE (decl) == VOID_TYPE
+ if (decl == NULL_TREE || VOID_TYPE_P (decl)
|| decl == error_mark_node)
return error_mark_node;
/* If this is a typedef that names the class for linkage purposes
(7.1.3p8), apply any attributes directly to the type. */
if (TREE_CODE (decl) == TYPE_DECL
- && TAGGED_TYPE_P (TREE_TYPE (decl))
+ && OVERLOAD_TYPE_P (TREE_TYPE (decl))
&& decl == TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (decl))))
flags = ATTR_FLAG_TYPE_IN_PLACE;
else
if (TYPE_P (context) && COMPLETE_TYPE_P (complete_type (context)))
{
- if (TREE_CODE (decl) == VAR_DECL)
+ if (VAR_P (decl))
{
tree field = lookup_field (context, DECL_NAME (decl), 0, false);
- if (field == NULL_TREE || TREE_CODE (field) != VAR_DECL)
+ if (field == NULL_TREE || !VAR_P (field))
error ("%q#D is not a static member of %q#T", decl, context);
else
{
if (decl == error_mark_node)
return error_mark_node;
- if (TREE_CODE (decl) == VAR_DECL
+ if (VAR_P (decl)
&& DECL_NAMESPACE_SCOPE_P (decl) && !TREE_PUBLIC (decl) && !was_public
&& !DECL_THIS_STATIC (decl) && !DECL_ARTIFICIAL (decl))
{
DECL_THIS_STATIC (decl) = 1;
}
- if (!processing_template_decl && TREE_CODE (decl) == VAR_DECL)
+ if (!processing_template_decl && VAR_P (decl))
start_decl_1 (decl, initialized);
return decl;
if (error_operand_p (decl))
return;
- gcc_assert (TREE_CODE (decl) == VAR_DECL);
+ gcc_assert (VAR_P (decl));
type = TREE_TYPE (decl);
complete_p = COMPLETE_TYPE_P (type);
is valid, i.e., does not have a designated initializer. */
static bool
-check_array_designated_initializer (const constructor_elt *ce,
+check_array_designated_initializer (constructor_elt *ce,
unsigned HOST_WIDE_INT index)
{
/* Designated initializers for array elements are not supported. */
/* The parser only allows identifiers as designated
initializers. */
if (ce->index == error_mark_node)
- error ("name used in a GNU-style designated "
- "initializer for an array");
- else if (TREE_CODE (ce->index) == INTEGER_CST)
+ {
+ error ("name used in a GNU-style designated "
+ "initializer for an array");
+ return false;
+ }
+ else if (identifier_p (ce->index))
+ {
+ error ("name %qD used in a GNU-style designated "
+ "initializer for an array", ce->index);
+ return false;
+ }
+
+ ce->index = cxx_constant_value (ce->index);
+
+ if (TREE_CODE (ce->index) == INTEGER_CST)
{
/* A C99 designator is OK if it matches the current index. */
- if (TREE_INT_CST_LOW (ce->index) == index)
+ if (wi::eq_p (ce->index, index))
return true;
else
sorry ("non-trivial designated initializers not supported");
}
else
- {
- gcc_assert (TREE_CODE (ce->index) == IDENTIFIER_NODE);
- error ("name %qD used in a GNU-style designated "
- "initializer for an array", ce->index);
- }
+ gcc_unreachable ();
+
return false;
}
if (type == error_mark_node)
return;
- /* If we haven't already layed out this declaration, do so now.
+ /* If we haven't already laid out this declaration, do so now.
Note that we must not call complete type for an external object
because it's type might involve templates that we are not
supposed to instantiate yet. (And it's perfectly valid to say
/* ``Unless explicitly declared extern, a const object does not have
external linkage and must be initialized. ($8.4; $12.1)'' ARM
7.1.6 */
- if (TREE_CODE (decl) == VAR_DECL
+ if (VAR_P (decl)
&& TREE_CODE (type) != REFERENCE_TYPE
&& CP_TYPE_CONST_P (type)
&& !DECL_INITIAL (decl))
tsubst_flags_t complain)
{
tree new_init;
- bool sized_array_p = (max_index != NULL_TREE);
+ bool sized_array_p = (max_index && TREE_CONSTANT (max_index));
unsigned HOST_WIDE_INT max_index_cst = 0;
unsigned HOST_WIDE_INT index;
if (integer_all_onesp (max_index))
return new_init;
- if (host_integerp (max_index, 1))
- max_index_cst = tree_low_cst (max_index, 1);
+ if (tree_fits_uhwi_p (max_index))
+ max_index_cst = tree_to_uhwi (max_index);
/* sizetype is sign extended, not zero extended. */
else
- max_index_cst = tree_low_cst (fold_convert (size_type_node, max_index),
- 1);
+ max_index_cst = tree_to_uhwi (fold_convert (size_type_node, max_index));
}
/* Loop until there are no more initializers. */
/* Handle designated initializers, as an extension. */
if (d->cur->index)
{
+ if (d->cur->index == error_mark_node)
+ return error_mark_node;
+
if (TREE_CODE (d->cur->index) == INTEGER_CST)
{
if (complain & tf_error)
error ("elements of array %q#T have incomplete type", type);
return true;
}
- /* It is not valid to initialize a VLA. */
- if (init
+ /* A compound literal can't have variable size. */
+ if (init && !decl
&& ((COMPLETE_TYPE_P (type) && !TREE_CONSTANT (TYPE_SIZE (type)))
|| !TREE_CONSTANT (TYPE_SIZE (element_type))))
{
- if (decl)
- error ("variable-sized object %qD may not be initialized", decl);
- else
- error ("variable-sized compound literal");
+ error ("variable-sized compound literal");
return true;
}
return false;
if ((type_build_ctor_call (type) || CLASS_TYPE_P (type))
&& !(flags & LOOKUP_ALREADY_DIGESTED)
&& !(init && BRACE_ENCLOSED_INITIALIZER_P (init)
- && CP_AGGREGATE_TYPE_P (type)))
+ && CP_AGGREGATE_TYPE_P (type)
+ && (CLASS_TYPE_P (type)
+ || !TYPE_NEEDS_CONSTRUCTING (type)
+ || type_has_extended_temps (type))))
{
init_code = build_aggr_init_full_exprs (decl, init, flags);
&& (!init || TREE_CODE (init) == TREE_LIST))
{
init = build_functional_cast (type, init, tf_none);
- if (init != error_mark_node)
+ if (TREE_CODE (init) == TARGET_EXPR)
TARGET_EXPR_DIRECT_INIT_P (init) = true;
}
init_code = NULL_TREE;
{
static int explained = 0;
- if (cxx_dialect < cxx0x)
+ if (cxx_dialect < cxx11)
error ("initializer invalid for static member with constructor");
else
error ("non-constant in-class initialization invalid for static "
/* The `register' keyword, when used together with an
asm-specification, indicates that the variable should be
placed in a particular register. */
- if (TREE_CODE (decl) == VAR_DECL && DECL_REGISTER (decl))
+ if (VAR_P (decl) && DECL_REGISTER (decl))
{
set_user_assembler_name (decl, asmspec);
DECL_HARD_REGISTER (decl) = 1;
}
/* Handle non-variables up front. */
- if (TREE_CODE (decl) != VAR_DECL)
+ if (!VAR_P (decl))
{
rest_of_decl_compilation (decl, toplev, at_eof);
return;
tree cleanup;
int already_used;
- gcc_assert (TREE_CODE (decl) == VAR_DECL
+ gcc_assert (VAR_P (decl)
|| TREE_CODE (decl) == RESULT_DECL);
gcc_assert (!TREE_STATIC (decl));
tree d_init;
if (init == NULL_TREE)
{
+ if (DECL_LANG_SPECIFIC (decl)
+ && DECL_TEMPLATE_INSTANTIATION (decl)
+ && !DECL_TEMPLATE_INSTANTIATED (decl))
+ {
+ /* init is null because we're deferring instantiating the
+ initializer until we need it. Well, we need it now. */
+ instantiate_decl (decl, /*defer_ok*/true, /*expl*/false);
+ return;
+ }
+
error ("declaration of %q#D has no initializer", decl);
TREE_TYPE (decl) = error_mark_node;
return;
auto_node);
if (type == error_mark_node)
return;
+ cp_apply_type_quals_to_decl (cp_type_quals (type), decl);
}
if (!ensure_literal_type_for_constexpr_object (decl))
DECL_DECLARED_CONSTEXPR_P (decl) = 0;
- if (TREE_CODE (decl) == VAR_DECL
+ if (VAR_P (decl)
&& DECL_CLASS_SCOPE_P (decl)
&& DECL_INITIALIZED_IN_CLASS_P (decl))
check_static_variable_definition (decl, type);
}
}
- if (init && TREE_CODE (decl) == VAR_DECL)
+ if (init && VAR_P (decl))
{
DECL_NONTRIVIALLY_INITIALIZED_P (decl) = 1;
/* If DECL is a reference, then we want to know whether init is a
then it can be used in future constant expressions, so its value
must be available. */
- if (TREE_CODE (decl) != VAR_DECL || dependent_type_p (type))
+ if (!VAR_P (decl) || dependent_type_p (type))
/* We can't do anything if the decl has dependent type. */;
else if (init
&& init_const_expr_p
TREE_READONLY (decl) = 0;
}
- if (TREE_CODE (decl) == VAR_DECL)
+ if (VAR_P (decl))
{
/* If this is a local variable that will need a mangled name,
register it now. We must do this before processing the
cleanups = make_tree_vector ();
init = check_initializer (decl, init, flags, &cleanups);
- /* Check that the initializer for a static data member was a
- constant. Although we check in the parser that the
- initializer is an integral constant expression, we do not
- simplify division-by-zero at the point at which it
- occurs. Therefore, in:
-
- struct S { static const int i = 7 / 0; };
-
- we issue an error at this point. It would
- probably be better to forbid division by zero in
- integral constant expressions. */
- if (DECL_EXTERNAL (decl) && init)
- {
- error ("%qD cannot be initialized by a non-constant expression"
- " when being declared", decl);
- DECL_INITIALIZED_IN_CLASS_P (decl) = 0;
- init = NULL_TREE;
- }
-
/* Handle:
[dcl.init]
/* Let the middle end know about variables and functions -- but not
static data members in uninstantiated class templates. */
- if (TREE_CODE (decl) == VAR_DECL
- || TREE_CODE (decl) == FUNCTION_DECL)
+ if (VAR_OR_FUNCTION_DECL_P (decl))
{
- if (TREE_CODE (decl) == VAR_DECL)
+ if (VAR_P (decl))
{
layout_var_decl (decl);
maybe_commonize_var (decl);
}
else if (was_readonly)
TREE_READONLY (decl) = 1;
+
+ /* Likewise if it needs destruction. */
+ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+ TREE_READONLY (decl) = 0;
}
make_rtl_for_nonlocal_decl (decl, init, asmspec);
/* Check for abstractness of the type. Notice that there is no
need to strip array types here since the check for those types
is already done within create_array_type_for_decl. */
- if (TREE_CODE (type) == FUNCTION_TYPE
- || TREE_CODE (type) == METHOD_TYPE)
- abstract_virtuals_error (decl, TREE_TYPE (type));
- else
- abstract_virtuals_error (decl, type);
+ abstract_virtuals_error (decl, type);
if (TREE_TYPE (decl) == error_mark_node)
/* No initialization required. */
/* Now, build the function declaration. */
push_lang_context (lang_name_c);
- atexit_fndecl = build_library_fn_ptr (name, fn_type);
+ atexit_fndecl = build_library_fn_ptr (name, fn_type, ECF_LEAF | ECF_NOTHROW);
mark_used (atexit_fndecl);
pop_lang_context ();
atexit_node = decay_conversion (atexit_fndecl, tf_warning_or_error);
NULL_TREE);
/* Now, build the function declaration. */
- tree atexit_fndecl = build_library_fn_ptr ("__cxa_thread_atexit", fn_type);
+ tree atexit_fndecl = build_library_fn_ptr ("__cxa_thread_atexit", fn_type,
+ ECF_LEAF | ECF_NOTHROW);
return decay_conversion (atexit_fndecl, tf_warning_or_error);
}
"__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
function to do the cleanup. */
- ob_parm = (DECL_THREAD_LOCAL_P (decl)
- || (flag_use_cxa_atexit
- && !targetm.cxx.use_atexit_for_cxa_atexit ()));
- dso_parm = ob_parm;
+ dso_parm = (flag_use_cxa_atexit
+ && !targetm.cxx.use_atexit_for_cxa_atexit ());
+ ob_parm = (DECL_THREAD_LOCAL_P (decl) || dso_parm);
use_dtor = ob_parm && CLASS_TYPE_P (type);
if (use_dtor)
{
before passing it in, to avoid spurious errors. */
addr = build_nop (ptr_type_node, addr);
}
- else if (ob_parm)
+ else
/* Since the cleanup functions we build ignore the address
they're given, there's no reason to pass the actual address
in, and, in general, it's cheaper to pass NULL than any
if (dso_parm)
arg2 = cp_build_addr_expr (get_dso_handle_node (),
tf_warning_or_error);
+ else if (ob_parm)
+ /* Just pass NULL to the dso handle parm if we don't actually
+ have a DSO handle on this target. */
+ arg2 = null_pointer_node;
else
arg2 = NULL_TREE;
static void
expand_static_init (tree decl, tree init)
{
- gcc_assert (TREE_CODE (decl) == VAR_DECL);
+ gcc_assert (VAR_P (decl));
gcc_assert (TREE_STATIC (decl));
/* Some variables require no dynamic initialization. */
if (!init
&& TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
- return;
+ {
+ /* Make sure the destructor is callable. */
+ cxx_maybe_build_cleanup (decl, tf_warning_or_error);
+ return;
+ }
if (DECL_THREAD_LOCAL_P (decl) && DECL_GNU_TLS_P (decl)
&& !DECL_FUNCTION_SCOPE_P (decl))
(acquire_name, build_function_type_list (integer_type_node,
TREE_TYPE (guard_addr),
NULL_TREE),
- NULL_TREE);
+ NULL_TREE, ECF_NOTHROW | ECF_LEAF);
if (!release_fn || !abort_fn)
vfntype = build_function_type_list (void_type_node,
TREE_TYPE (guard_addr),
NULL_TREE);
if (!release_fn)
- release_fn = push_library_fn (release_name, vfntype, NULL_TREE);
+ release_fn = push_library_fn (release_name, vfntype, NULL_TREE,
+ ECF_NOTHROW | ECF_LEAF);
if (!abort_fn)
- abort_fn = push_library_fn (abort_name, vfntype, NULL_TREE);
+ abort_fn = push_library_fn (abort_name, vfntype, NULL_TREE,
+ ECF_NOTHROW | ECF_LEAF);
inner_if_stmt = begin_if_stmt ();
finish_if_stmt_cond (build_call_n (acquire_fn, 1, guard_addr),
{
/* These checks only apply to member functions and static data
members. */
- gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
- || TREE_CODE (decl) == VAR_DECL);
+ gcc_assert (VAR_OR_FUNCTION_DECL_P (decl));
/* We check for problems with specializations in pt.c in
check_specialization_namespace, where we can issue better
diagnostics. */
decl);
}
+/* Helper function. Replace the temporary this parameter injected
+ during cp_finish_omp_declare_simd with the real this parameter. */
+
+static tree
+declare_simd_adjust_this (tree *tp, int *walk_subtrees, void *data)
+{
+ tree this_parm = (tree) data;
+ if (TREE_CODE (*tp) == PARM_DECL
+ && DECL_NAME (*tp) == this_identifier
+ && *tp != this_parm)
+ *tp = this_parm;
+ else if (TYPE_P (*tp))
+ *walk_subtrees = 0;
+ return NULL_TREE;
+}
+
/* CTYPE is class type, or null if non-class.
TYPE is type this FUNCTION_DECL should have, either FUNCTION_TYPE
or METHOD_TYPE.
int virtualp,
enum overload_flags flags,
cp_cv_quals quals,
+ cp_ref_qualifier rqual,
tree raises,
int check,
int friendp,
int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE;
tree t;
+ if (rqual)
+ type = build_ref_qualified_type (type, rqual);
if (raises)
type = build_exception_variant (type, raises);
the information in the TEMPLATE_ID_EXPR. */
SET_DECL_IMPLICIT_INSTANTIATION (decl);
- if (TREE_CODE (fns) == COMPONENT_REF)
- {
- /* Due to bison parser ickiness, we will have already looked
- up an operator_name or PFUNCNAME within the current class
- (see template_id in parse.y). If the current class contains
- such a name, we'll get a COMPONENT_REF here. Undo that. */
-
- gcc_assert (TREE_TYPE (TREE_OPERAND (fns, 0))
- == current_class_type);
- fns = TREE_OPERAND (fns, 1);
- }
- gcc_assert (TREE_CODE (fns) == IDENTIFIER_NODE
- || TREE_CODE (fns) == OVERLOAD);
+ gcc_assert (identifier_p (fns) || TREE_CODE (fns) == OVERLOAD);
DECL_TEMPLATE_INFO (decl) = build_template_info (fns, args);
for (t = TYPE_ARG_TYPES (TREE_TYPE (decl)); t; t = TREE_CHAIN (t))
return NULL_TREE;
}
+ if (inlinep & 1)
+ error ("%<inline%> is not allowed in declaration of friend "
+ "template specialization %qD",
+ decl);
+ if (inlinep & 2)
+ error ("%<constexpr%> is not allowed in declaration of friend "
+ "template specialization %qD",
+ decl);
if (inlinep)
- {
- error ("%<inline%> is not allowed in declaration of friend "
- "template specialization %qD",
- decl);
- return NULL_TREE;
- }
+ return NULL_TREE;
}
}
|| (IDENTIFIER_LENGTH (declarator) > 10
&& IDENTIFIER_POINTER (declarator)[0] == '_'
&& IDENTIFIER_POINTER (declarator)[1] == '_'
- && strncmp (IDENTIFIER_POINTER (declarator)+2, "builtin_", 8) == 0))
+ && strncmp (IDENTIFIER_POINTER (declarator)+2, "builtin_", 8) == 0)
+ || (targetcm.cxx_implicit_extern_c
+ && targetcm.cxx_implicit_extern_c(IDENTIFIER_POINTER (declarator))))
&& current_lang_name == lang_name_cplusplus
&& ctype == NULL_TREE
&& DECL_FILE_SCOPE_P (decl))
{
if (PROCESSING_REAL_TEMPLATE_DECL_P())
error ("cannot declare %<::main%> to be a template");
- if (inlinep)
+ if (inlinep & 1)
error ("cannot declare %<::main%> to be inline");
+ if (inlinep & 2)
+ error ("cannot declare %<::main%> to be constexpr");
if (!publicp)
error ("cannot declare %<::main%> to be static");
inlinep = 0;
DECL_DECLARED_CONSTEXPR_P (decl) = true;
DECL_EXTERNAL (decl) = 1;
- if (quals && TREE_CODE (type) == FUNCTION_TYPE)
+ if (TREE_CODE (type) == FUNCTION_TYPE)
{
- error (ctype
- ? G_("static member function %qD cannot have cv-qualifier")
- : G_("non-member function %qD cannot have cv-qualifier"),
- decl);
- quals = TYPE_UNQUALIFIED;
+ if (quals)
+ {
+ error (ctype
+ ? G_("static member function %qD cannot have cv-qualifier")
+ : G_("non-member function %qD cannot have cv-qualifier"),
+ decl);
+ quals = TYPE_UNQUALIFIED;
+ }
+
+ if (rqual)
+ {
+ error (ctype
+ ? G_("static member function %qD cannot have ref-qualifier")
+ : G_("non-member function %qD cannot have ref-qualifier"),
+ decl);
+ rqual = REF_QUAL_NONE;
+ }
}
if (IDENTIFIER_OPNAME_P (DECL_NAME (decl))
if (TYPE_NOTHROW_P (type) || nothrow_libfn_p (decl))
TREE_NOTHROW (decl) = 1;
+ if (flag_openmp)
+ {
+ /* Adjust "omp declare simd" attributes. */
+ tree ods = lookup_attribute ("omp declare simd", *attrlist);
+ if (ods)
+ {
+ tree attr;
+ for (attr = ods; attr;
+ attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr)))
+ {
+ if (TREE_CODE (type) == METHOD_TYPE)
+ walk_tree (&TREE_VALUE (attr), declare_simd_adjust_this,
+ DECL_ARGUMENTS (decl), NULL);
+ if (TREE_VALUE (attr) != NULL_TREE)
+ {
+ tree cl = TREE_VALUE (TREE_VALUE (attr));
+ cl = c_omp_declare_simd_clauses_to_numbers
+ (DECL_ARGUMENTS (decl), cl);
+ if (cl)
+ TREE_VALUE (TREE_VALUE (attr)) = cl;
+ else
+ TREE_VALUE (attr) = NULL_TREE;
+ }
+ }
+ }
+ }
+
/* Caller will do the rest of this. */
if (check < 0)
return decl;
grokclassfn (ctype, decl, flags);
/* 12.4/3 */
- if (cxx_dialect >= cxx0x
+ if (cxx_dialect >= cxx11
&& DECL_DESTRUCTOR_P (decl)
&& !TYPE_BEING_DEFINED (DECL_CONTEXT (decl))
&& !processing_template_decl)
tree decl;
tree explicit_scope;
- gcc_assert (!name || TREE_CODE (name) == IDENTIFIER_NODE);
+ gcc_assert (!name || identifier_p (name));
/* Compute the scope in which to place the variable, but remember
whether or not that scope was explicitly specified by the user. */
if (TREE_CODE (member_type) == METHOD_TYPE)
{
cp_cv_quals quals = type_memfn_quals (member_type);
- member_type = build_memfn_type (member_type, class_type, quals);
+ cp_ref_qualifier rqual = type_memfn_rqual (member_type);
+ member_type = build_memfn_type (member_type, class_type, quals, rqual);
return build_ptrmemfunc_type (build_pointer_type (member_type));
}
else
in check_initializer. */
if (DECL_P (decl) && DECL_DECLARED_CONSTEXPR_P (decl))
return 0;
- else if (cxx_dialect >= cxx0x && !INTEGRAL_OR_ENUMERATION_TYPE_P (type))
+ else if (cxx_dialect >= cxx11 && !INTEGRAL_OR_ENUMERATION_TYPE_P (type))
{
if (!COMPLETE_TYPE_P (type))
error ("in-class initialization of static data member %q#D of "
mark_rvalue_use (size);
- if (cxx_dialect < cxx0x && TREE_CODE (size) == NOP_EXPR
+ if (cxx_dialect < cxx11 && TREE_CODE (size) == NOP_EXPR
&& TREE_SIDE_EFFECTS (size))
/* In C++98, we mark a non-constant array bound with a magic
NOP_EXPR with TREE_SIDE_EFFECTS; don't fold in that case. */;
constant. Just build the index type and mark that it requires
structural equality checks. */
itype = build_index_type (build_min (MINUS_EXPR, sizetype,
- size, integer_one_node));
+ size, size_one_node));
TYPE_DEPENDENT_P (itype) = 1;
TYPE_DEPENDENT_P_VALID (itype) = 1;
SET_TYPE_STRUCTURAL_EQUALITY (itype);
else if (TREE_CONSTANT (size)
/* We don't allow VLAs at non-function scopes, or during
tentative template substitution. */
- || !at_function_scope_p () || !(complain & tf_error))
+ || !at_function_scope_p ()
+ || (cxx_dialect < cxx1y && !(complain & tf_error)))
{
if (!(complain & tf_error))
return error_mark_node;
error ("size of array is not an integral constant-expression");
size = integer_one_node;
}
- else if (pedantic && warn_vla != 0)
+ else if (cxx_dialect < cxx1y && pedantic && warn_vla != 0)
{
if (name)
pedwarn (input_location, OPT_Wvla, "ISO C++ forbids variable length array %qD", name);
{
/* A variable sized array. */
itype = variable_size (itype);
+
if (TREE_CODE (itype) != SAVE_EXPR)
{
/* Look for SIZEOF_EXPRs in itype and fold them, otherwise
if (found)
itype = variable_size (fold (newitype));
}
+
+ stabilize_vla_size (itype);
+
+ if (cxx_dialect >= cxx1y)
+ {
+ /* If the VLA bound is larger than half the address space,
+ or less than zero, throw std::bad_array_length. */
+ tree comp = build2 (LT_EXPR, boolean_type_node, itype,
+ ssize_int (-1));
+ comp = build3 (COND_EXPR, void_type_node, comp,
+ throw_bad_array_length (), void_zero_node);
+ finish_expr_stmt (comp);
+ }
+ else if (flag_sanitize & SANITIZE_VLA)
+ {
+ /* From C++1y onwards, we throw an exception on a negative
+ length size of an array; see above. */
+
+ /* We have to add 1 -- in the ubsan routine we generate
+ LE_EXPR rather than LT_EXPR. */
+ tree t = fold_build2 (PLUS_EXPR, TREE_TYPE (itype), itype,
+ build_one_cst (TREE_TYPE (itype)));
+ t = fold_build2 (COMPOUND_EXPR, TREE_TYPE (t),
+ ubsan_instrument_vla (input_location, t), t);
+ finish_expr_stmt (t);
+ }
}
/* Make sure that there was no overflow when creating to a signed
index type. (For example, on a 32-bit machine, an array with
return error_mark_node;
}
+ if (cxx_dialect >= cxx1y && array_of_runtime_bound_p (type))
+ pedwarn (input_location, OPT_Wvla, "array of array of runtime bound");
+
/* Figure out the index type for the array. */
if (size)
itype = compute_array_index_type (name, size, tf_warning_or_error);
{
if (!identifier)
error ("unnamed variable or field declared void");
- else if (TREE_CODE (identifier) == IDENTIFIER_NODE)
+ else if (identifier_p (identifier))
{
gcc_assert (!IDENTIFIER_OPNAME_P (identifier));
error ("variable or field %qE declared void", identifier);
return type;
}
+/* Functions for adjusting the visibility of a tagged type and its nested
+ types when it gets a name for linkage purposes from a typedef. */
+
+static void bt_reset_linkage (binding_entry, void *);
+static void
+reset_type_linkage (tree type)
+{
+ set_linkage_according_to_type (type, TYPE_MAIN_DECL (type));
+ if (CLASS_TYPE_P (type))
+ binding_table_foreach (CLASSTYPE_NESTED_UTDS (type), bt_reset_linkage, NULL);
+}
+static void
+bt_reset_linkage (binding_entry b, void */*data*/)
+{
+ reset_type_linkage (b->type);
+}
+
/* Given declspecs and a declarator (abstract or otherwise), determine
the name and type of the object declared and construct a DECL node
for it.
int explicit_int = 0;
int explicit_char = 0;
int defaulted_int = 0;
- tree dependent_name = NULL_TREE;
tree typedef_decl = NULL_TREE;
const char *name = NULL;
/* virt-specifiers that apply to the declarator, for a declaration of
a member function. */
cp_virt_specifiers virt_specifiers = VIRT_SPEC_UNSPECIFIED;
+ /* ref-qualifier that applies to the declarator, for a declaration of
+ a member function. */
+ cp_ref_qualifier rqual = REF_QUAL_NONE;
/* cv-qualifiers that apply to the type specified by the DECLSPECS. */
int type_quals;
tree raises = NULL_TREE;
bool parameter_pack_p = declarator? declarator->parameter_pack_p : false;
bool template_type_arg = false;
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);
+ source_location saved_loc = input_location;
const char *errmsg;
signed_p = decl_spec_seq_has_spec_p (declspecs, ds_signed);
&& !uniquely_derived_from_p (ctype,
current_class_type))
{
- error ("type %qT is not derived from type %qT",
- ctype, current_class_type);
+ error ("invalid use of qualified-name %<%T::%D%>",
+ qualifying_scope, decl);
return error_mark_node;
}
}
tree fns = TREE_OPERAND (decl, 0);
dname = fns;
- if (TREE_CODE (dname) != IDENTIFIER_NODE)
+ if (!identifier_p (dname))
{
gcc_assert (is_overloaded_fn (dname));
dname = DECL_NAME (get_first_fn (dname));
/* Fall through. */
case IDENTIFIER_NODE:
- if (TREE_CODE (decl) == IDENTIFIER_NODE)
+ if (identifier_p (decl))
dname = decl;
if (C_IS_RESERVED_WORD (dname))
}
if (dname
- && TREE_CODE (dname) == IDENTIFIER_NODE
+ && identifier_p (dname)
&& UDLIT_OPER_P (dname)
&& innermost_code != cdk_function)
{
if (dname && IDENTIFIER_OPNAME_P (dname))
{
- if (decl_spec_seq_has_spec_p (declspecs, ds_typedef))
+ if (typedef_p)
{
error ("declaration of %qD as %<typedef%>", dname);
return error_mark_node;
if (name == NULL)
name = decl_context == PARM ? "parameter" : "type name";
- if (constexpr_p && decl_spec_seq_has_spec_p (declspecs, ds_typedef))
+ if (constexpr_p && typedef_p)
{
error ("%<constexpr%> cannot appear in a typedef declaration");
return error_mark_node;
common. With no options, it is allowed. With -Wreturn-type,
it is a warning. It is only an error with -pedantic-errors. */
is_main = (funcdef_flag
- && dname && TREE_CODE (dname) == IDENTIFIER_NODE
+ && dname && identifier_p (dname)
&& MAIN_NAME_P (dname)
&& ctype == NULL_TREE
&& in_namespace == NULL_TREE
}
friendp = decl_spec_seq_has_spec_p (declspecs, ds_friend);
- if (dependent_name && !friendp)
- {
- error ("%<%T::%D%> is not a valid declarator", ctype, dependent_name);
- return error_mark_node;
- }
-
/* Issue errors about use of storage classes for parameters. */
if (decl_context == PARM)
{
- if (decl_spec_seq_has_spec_p (declspecs, ds_typedef))
+ if (typedef_p)
{
error ("typedef declaration invalid in parameter declaration");
return error_mark_node;
&& ((storage_class
&& storage_class != sc_extern
&& storage_class != sc_static)
- || decl_spec_seq_has_spec_p (declspecs, ds_typedef)))
+ || typedef_p))
{
error ("multiple storage classes in declaration of %qs", name);
thread_p = false;
&& (storage_class == sc_register
|| storage_class == sc_auto))
;
- else if (decl_spec_seq_has_spec_p (declspecs, ds_typedef))
+ else if (typedef_p)
;
else if (decl_context == FIELD
/* C++ allows static class elements. */
if (declspecs->std_attributes)
{
/* Apply the c++11 attributes to the type preceding them. */
- source_location saved_loc = input_location;
input_location = declspecs->locations[ds_std_attribute];
decl_attributes (&type, declspecs->std_attributes, 0);
input_location = saved_loc;
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);
+
+ input_location = declspecs->locations[ds_type_spec];
+ abstract_virtuals_error (ACU_RETURN, type);
+ input_location = saved_loc;
/* Pick up type qualifiers which should be applied to `this'. */
memfn_quals = declarator->u.function.qualifiers;
/* Pick up virt-specifiers. */
virt_specifiers = declarator->u.function.virt_specifiers;
+ /* And ref-qualifier, too */
+ rqual = declarator->u.function.ref_qualifier;
/* Pick up the exception specifications. */
raises = declarator->u.function.exception_specification;
/* If the exception-specification is ill-formed, let's pretend
pedwarn (input_location, 0, "%qs function uses "
"%<auto%> type specifier without trailing "
"return type", name);
+ else if (virtualp)
+ permerror (input_location, "virtual function cannot "
+ "have deduced return type");
}
else if (!is_auto (type))
{
}
else if (declarator->u.function.late_return_type)
{
- if (cxx_dialect < cxx0x)
+ if (cxx_dialect < cxx11)
/* Not using maybe_warn_cpp0x because this should
always be an error. */
error ("trailing return type only available with "
therefore returns a void type. */
/* ISO C++ 12.4/2. A destructor may not be declared
- const or volatile. A destructor may not be
- static.
+ const or volatile. A destructor may not be static.
+ A destructor may not be declared with ref-qualifier.
ISO C++ 12.1. A constructor may not be declared
const or volatile. A constructor may not be
- virtual. A constructor may not be static. */
+ 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")
memfn_quals = TYPE_UNQUALIFIED;
}
+ if (rqual)
+ {
+ maybe_warn_cpp0x (CPP0X_REF_QUALIFIER);
+ error ((flags == DTOR_FLAG)
+ ? "destructors may not be ref-qualified"
+ : "constructors may not be ref-qualified");
+ rqual = REF_QUAL_NONE;
+ }
+
if (decl_context == FIELD
&& !member_function_or_else (ctype,
current_class_type,
but to the target of the pointer. */
type_quals = TYPE_UNQUALIFIED;
+ /* This code used to handle METHOD_TYPE, but I don't think it's
+ possible to get it here anymore. */
+ gcc_assert (TREE_CODE (type) != METHOD_TYPE);
if (declarator->kind == cdk_ptrmem
- && (TREE_CODE (type) == FUNCTION_TYPE
- || (memfn_quals && TREE_CODE (type) == METHOD_TYPE)))
+ && TREE_CODE (type) == FUNCTION_TYPE)
{
memfn_quals |= type_memfn_quals (type);
type = build_memfn_type (type,
declarator->u.pointer.class_type,
- memfn_quals);
+ memfn_quals,
+ rqual);
if (type == error_mark_node)
return error_mark_node;
+
+ rqual = REF_QUAL_NONE;
memfn_quals = TYPE_UNQUALIFIED;
}
if (TREE_CODE (type) == FUNCTION_TYPE
- && type_memfn_quals (type) != TYPE_UNQUALIFIED)
+ && (type_memfn_quals (type) != TYPE_UNQUALIFIED
+ || type_memfn_rqual (type) != REF_QUAL_NONE))
error (declarator->kind == cdk_reference
? G_("cannot declare reference to qualified function type %qT")
: G_("cannot declare pointer to qualified function type %qT"),
type);
+ if (cxx_dialect >= cxx1y && array_of_runtime_bound_p (type))
+ pedwarn (input_location, OPT_Wvla,
+ declarator->kind == cdk_reference
+ ? G_("reference to array of runtime bound")
+ : G_("pointer to array of runtime bound"));
+
/* When the pointed-to type involves components of variable size,
care must be taken to ensure that the size evaluation code is
emitted early enough to dominate all the possible later uses
&& (decl_context == NORMAL || decl_context == FIELD)
&& at_function_scope_p ()
&& variably_modified_type_p (type, NULL_TREE))
- {
- /* First break out any side-effects. */
- stabilize_vla_size (TYPE_SIZE (type));
- /* And then force evaluation of the SAVE_EXPR. */
- finish_expr_stmt (TYPE_SIZE (type));
- }
+ /* Force evaluation of the SAVE_EXPR. */
+ finish_expr_stmt (TYPE_SIZE (type));
if (declarator->kind == cdk_reference)
{
}
}
- /* We need to stabilize side-effects in VLA sizes for regular array
- declarations too, not just pointers to arrays. */
- if (type != error_mark_node && !TYPE_NAME (type)
- && (decl_context == NORMAL || decl_context == FIELD)
- && at_function_scope_p ()
- && variably_modified_type_p (type, NULL_TREE))
- stabilize_vla_size (TYPE_SIZE (type));
-
/* A `constexpr' specifier used in an object declaration declares
the object as `const'. */
if (constexpr_p && innermost_code != cdk_function)
return error_mark_node;
}
}
- else if (decl_spec_seq_has_spec_p (declspecs, ds_typedef)
- && current_class_type)
+ else if (typedef_p && current_class_type)
{
error ("cannot declare member %<%T::%s%> within %qT",
ctype, name, current_class_type);
{
error ("size of array %qs is too large", name);
/* If we proceed with the array type as it is, we'll eventually
- crash in tree_low_cst(). */
+ crash in tree_to_[su]hwi(). */
type = error_mark_node;
}
error ("non-member %qs cannot be declared %<mutable%>", name);
storage_class = sc_none;
}
- else if (decl_context == TYPENAME
- || decl_spec_seq_has_spec_p (declspecs, ds_typedef))
+ else if (decl_context == TYPENAME || typedef_p)
{
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 (decl_spec_seq_has_spec_p (declspecs, ds_typedef) && decl_context != TYPENAME)
+ if (typedef_p && decl_context != TYPENAME)
{
tree decl;
example "f S::*" declares a pointer to a const-qualified
member function of S. We record the cv-qualification in the
function type. */
- if (memfn_quals && TREE_CODE (type) == FUNCTION_TYPE)
+ if ((rqual || memfn_quals) && TREE_CODE (type) == FUNCTION_TYPE)
{
- type = apply_memfn_quals (type, memfn_quals);
+ type = apply_memfn_quals (type, memfn_quals, rqual);
/* We have now dealt with these qualifiers. */
memfn_quals = TYPE_UNQUALIFIED;
+ rqual = REF_QUAL_NONE;
}
if (type_uses_auto (type))
type = error_mark_node;
}
+ if (cxx_dialect >= cxx1y && array_of_runtime_bound_p (type))
+ pedwarn (input_location, OPT_Wvla,
+ "typedef naming array of runtime bound");
+
if (decl_context == FIELD)
decl = build_lang_decl (TYPE_DECL, unqualified_id, type);
else
= TYPE_IDENTIFIER (type);
/* Adjust linkage now that we aren't anonymous anymore. */
- set_linkage_according_to_type (type, TYPE_MAIN_DECL (type));
- determine_visibility (TYPE_MAIN_DECL (type));
+ reset_type_linkage (type);
/* FIXME remangle member functions; member functions of a
type with external linkage have external linkage. */
if (decl_context != TYPENAME)
{
/* A cv-qualifier-seq shall only be part of the function type
- for a non-static member function. [8.3.5/4 dcl.fct] */
- if (type_memfn_quals (type) != TYPE_UNQUALIFIED
+ for a non-static member function. A ref-qualifier shall only
+ .... /same as above/ [dcl.fct] */
+ if ((type_memfn_quals (type) != TYPE_UNQUALIFIED
+ || type_memfn_rqual (type) != REF_QUAL_NONE)
&& (current_class_type == NULL_TREE || staticp) )
{
error (staticp
/* The qualifiers on the function type become the qualifiers on
the non-static member function. */
memfn_quals |= type_memfn_quals (type);
+ rqual = type_memfn_rqual (type);
type_quals = TYPE_UNQUALIFIED;
}
}
type = void_type_node;
}
}
- else if (memfn_quals)
+ else if (memfn_quals || rqual)
{
if (ctype == NULL_TREE
&& TREE_CODE (type) == METHOD_TYPE)
ctype = TYPE_METHOD_BASETYPE (type);
if (ctype)
- type = build_memfn_type (type, ctype, memfn_quals);
- /* Core issue #547: need to allow this in template type args. */
- else if (template_type_arg && TREE_CODE (type) == FUNCTION_TYPE)
- type = apply_memfn_quals (type, memfn_quals);
+ type = build_memfn_type (type, ctype, memfn_quals, rqual);
+ /* Core issue #547: need to allow this in template type args.
+ Allow it in general in C++11 for alias-declarations. */
+ else if ((template_type_arg || cxx_dialect >= cxx11)
+ && TREE_CODE (type) == FUNCTION_TYPE)
+ type = apply_memfn_quals (type, memfn_quals, rqual);
else
error ("invalid qualifiers on non-member function type");
}
if (type_uses_auto (type))
{
- error ("parameter declared %<auto%>");
+ if (cxx_dialect >= cxx1y)
+ error ("%<auto%> parameter not permitted in this context");
+ else
+ error ("parameter declared %<auto%>");
type = error_mark_node;
}
cp_cv_quals real_quals = memfn_quals;
if (constexpr_p && sfk != sfk_constructor && sfk != sfk_destructor)
real_quals |= TYPE_QUAL_CONST;
- type = build_memfn_type (type, ctype, real_quals);
+ type = build_memfn_type (type, ctype, real_quals, rqual);
}
{
? unqualified_id : dname,
parms,
unqualified_id,
- virtualp, flags, memfn_quals, raises,
+ virtualp, flags, memfn_quals, rqual, raises,
friendp ? -1 : 0, friendp, publicp,
inlinep | (2 * constexpr_p),
sfk,
&& (TREE_CODE (type) != ARRAY_TYPE || initialized == 0))
{
if (unqualified_id)
- error ("field %qD has incomplete type", unqualified_id);
+ error ("field %qD has incomplete type %qT",
+ unqualified_id, type);
else
error ("name %qT has incomplete type", type);
- /* If we're instantiating a template, tell them which
- instantiation made the field's type be incomplete. */
- if (current_class_type
- && TYPE_NAME (current_class_type)
- && IDENTIFIER_TEMPLATE (current_class_name)
- && declspecs->type
- && declspecs->type == type)
- error (" in instantiation of template %qT",
- current_class_type);
-
- return error_mark_node;
+ type = error_mark_node;
+ decl = NULL_TREE;
}
else
{
}
}
- /* Record presence of `static'. */
+ /* Record whether the function is public. */
publicp = (ctype != NULL_TREE
- || storage_class == sc_extern
|| storage_class != sc_static);
decl = grokfndecl (ctype, type, original_name, parms, unqualified_id,
- virtualp, flags, memfn_quals, raises,
+ virtualp, flags, memfn_quals, rqual, raises,
1, friendp,
publicp, inlinep | (2 * constexpr_p), sfk,
funcdef_flag,
DECL_THIS_STATIC (decl) = 1;
/* Set constexpr flag on vars (functions got it in grokfndecl). */
- if (constexpr_p && TREE_CODE (decl) == VAR_DECL)
+ if (constexpr_p && VAR_P (decl))
DECL_DECLARED_CONSTEXPR_P (decl) = true;
/* Record constancy and volatility on the DECL itself . There's
int
local_variable_p (const_tree t)
{
- if ((TREE_CODE (t) == VAR_DECL
+ if ((VAR_P (t)
/* A VAR_DECL with a context that is a _TYPE is a static data
member. */
&& !TYPE_P (CP_DECL_CONTEXT (t))
local_variable_p_walkfn (tree *tp, int *walk_subtrees,
void * /*data*/)
{
- /* Check DECL_NAME to avoid including temporaries. We don't check
- DECL_ARTIFICIAL because we do want to complain about 'this'. */
- if (local_variable_p (*tp) && DECL_NAME (*tp))
+ if (local_variable_p (*tp)
+ && (!DECL_ARTIFICIAL (*tp) || DECL_NAME (*tp) == this_identifier))
return *tp;
else if (TYPE_P (*tp))
*walk_subtrees = 0;
DECL, if there is no DECL available. */
tree
-check_default_argument (tree decl, tree arg)
+check_default_argument (tree decl, tree arg, tsubst_flags_t complain)
{
tree var;
tree decl_type;
A default argument expression is implicitly converted to the
parameter type. */
++cp_unevaluated_operand;
- perform_implicit_conversion_flags (decl_type, arg, tf_warning_or_error,
- LOOKUP_NORMAL);
+ perform_implicit_conversion_flags (decl_type, arg, complain,
+ LOOKUP_IMPLICIT);
--cp_unevaluated_operand;
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;
- }
+ && (complain & tf_warning)
+ && maybe_warn_zero_as_null_pointer_constant (arg, input_location))
+ return nullptr_node;
/* [dcl.fct.default]
var = cp_walk_tree_without_duplicates (&arg, local_variable_p_walkfn, NULL);
if (var)
{
- if (DECL_NAME (var) == this_identifier)
- permerror (input_location, "default argument %qE uses %qD", arg, var);
- else
- error ("default argument %qE uses local variable %qD", arg, var);
+ if (complain & tf_warning_or_error)
+ {
+ if (DECL_NAME (var) == this_identifier)
+ permerror (input_location, "default argument %qE uses %qD",
+ arg, var);
+ else
+ error ("default argument %qE uses local variable %qD", arg, var);
+ }
return error_mark_node;
}
return type;
/* Do warn about using typedefs to a deprecated class. */
- if (TAGGED_TYPE_P (type) && type != TYPE_MAIN_VARIANT (type))
+ if (OVERLOAD_TYPE_P (type) && type != TYPE_MAIN_VARIANT (type))
return type_is_deprecated (TYPE_MAIN_VARIANT (type));
code = TREE_CODE (type);
if (any_error)
init = NULL_TREE;
else if (init && !processing_template_decl)
- init = check_default_argument (decl, init);
+ init = check_default_argument (decl, init, tf_warning_or_error);
}
DECL_CHAIN (decl) = decls;
if (ref)
t = TYPE_MAIN_VARIANT (TREE_TYPE (t));
- if (TREE_CODE (t) == VOID_TYPE)
+ if (VOID_TYPE_P (t))
warning (OPT_Wconversion,
ref
? G_("conversion to a reference to void "
{
tree type;
- if (decl == error_mark_node)
- return error_mark_node;
-
/* In the case of:
struct S { struct S *p; };
&& tag_code != typename_type)
{
error ("%qT referred to as %qs", type, tag_name (tag_code));
- error ("%q+T has a previous declaration here", type);
+ inform (input_location, "%q+T has a previous declaration here", type);
return error_mark_node;
}
else if (TREE_CODE (type) != ENUMERAL_TYPE
&& tag_code == enum_type)
{
error ("%qT referred to as enum", type);
- error ("%q+T has a previous declaration here", type);
+ inform (input_location, "%q+T has a previous declaration here", type);
return error_mark_node;
}
else if (!allow_template_p
static tree
xref_tag_1 (enum tag_types tag_code, tree name,
- tag_scope scope, bool template_header_p)
+ tag_scope orig_scope, bool template_header_p)
{
enum tree_code code;
tree t;
tree context = NULL_TREE;
+ tag_scope scope;
- gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
+ gcc_assert (identifier_p (name));
switch (tag_code)
{
gcc_unreachable ();
}
+ if (orig_scope == ts_lambda)
+ scope = ts_current;
+ else
+ scope = orig_scope;
+
/* In case of anonymous name, xref_tag is only called to
make type node and push name. Name lookup is not required. */
if (ANON_AGGRNAME_P (name))
{
t = make_class_type (code);
TYPE_CONTEXT (t) = context;
+ if (orig_scope == ts_lambda)
+ /* Remember that we're declaring a lambda to avoid bogus errors
+ in push_template_decl. */
+ CLASSTYPE_LAMBDA_EXPR (t) = error_mark_node;
t = pushtag (name, t, scope);
}
}
bool scoped_enum_p, bool *is_new)
{
tree prevtype = NULL_TREE;
- gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
+ gcc_assert (identifier_p (name));
if (is_new)
*is_new = false;
enumeration. We must do this before the type of MINNODE and
MAXNODE are transformed, since tree_int_cst_min_precision relies
on the TREE_TYPE of the value it is passed. */
- bool unsignedp = tree_int_cst_sgn (minnode) >= 0;
- int lowprec = tree_int_cst_min_precision (minnode, unsignedp);
- int highprec = tree_int_cst_min_precision (maxnode, unsignedp);
+ signop sgn = tree_int_cst_sgn (minnode) >= 0 ? UNSIGNED : SIGNED;
+ int lowprec = tree_int_cst_min_precision (minnode, sgn);
+ int highprec = tree_int_cst_min_precision (maxnode, sgn);
int precision = MAX (lowprec, highprec);
unsigned int itk;
bool use_short_enum;
underlying_type = integer_types[itk];
if (underlying_type != NULL_TREE
&& TYPE_PRECISION (underlying_type) >= precision
- && TYPE_UNSIGNED (underlying_type) == unsignedp)
+ && TYPE_SIGN (underlying_type) == sgn)
break;
}
if (itk == itk_none)
= build_distinct_type_copy (underlying_type);
TYPE_PRECISION (ENUM_UNDERLYING_TYPE (enumtype)) = precision;
set_min_and_max_values_for_integral_type
- (ENUM_UNDERLYING_TYPE (enumtype), precision, unsignedp);
+ (ENUM_UNDERLYING_TYPE (enumtype), precision, sgn);
/* If -fstrict-enums, still constrain TYPE_MIN/MAX_VALUE. */
if (flag_strict_enums)
- set_min_and_max_values_for_integral_type (enumtype, precision,
- unsignedp);
+ set_min_and_max_values_for_integral_type (enumtype, precision, sgn);
}
else
underlying_type = ENUM_UNDERLYING_TYPE (enumtype);
value = error_mark_node;
else
{
- double_int di = TREE_INT_CST (prev_value)
- .add_with_sign (double_int_one,
- false, &overflowed);
+ tree type = TREE_TYPE (prev_value);
+ signop sgn = TYPE_SIGN (type);
+ widest_int wi = wi::add (wi::to_widest (prev_value), 1, sgn,
+ &overflowed);
if (!overflowed)
{
- tree type = TREE_TYPE (prev_value);
- bool pos = TYPE_UNSIGNED (type) || !di.is_negative ();
- if (!double_int_fits_to_tree_p (type, di))
+ bool pos = !wi::neg_p (wi, sgn);
+ if (!wi::fits_to_tree_p (wi, type))
{
unsigned int itk;
for (itk = itk_int; itk != itk_none; itk++)
type = integer_types[itk];
if (type != NULL_TREE
&& (pos || !TYPE_UNSIGNED (type))
- && double_int_fits_to_tree_p (type, di))
+ && wi::fits_to_tree_p (wi, type))
break;
}
- if (type && cxx_dialect < cxx0x
+ if (type && cxx_dialect < cxx11
&& itk > itk_unsigned_long)
pedwarn (input_location, OPT_Wlong_long, pos ? "\
incremented enumerator value is too large for %<unsigned long%>" : "\
if (type == NULL_TREE)
overflowed = true;
else
- value = double_int_to_tree (type, di);
+ value = wide_int_to_tree (type, wi);
}
if (overflowed)
does not fit, the program is ill-formed [C++0x dcl.enum]. */
if (ENUM_UNDERLYING_TYPE (enumtype)
&& value
- && TREE_CODE (value) == INTEGER_CST
- && !int_fits_type_p (value, ENUM_UNDERLYING_TYPE (enumtype)))
+ && TREE_CODE (value) == INTEGER_CST)
{
- error ("enumerator value %E is too large for underlying type %<%T%>",
- value, ENUM_UNDERLYING_TYPE (enumtype));
+ if (!int_fits_type_p (value, ENUM_UNDERLYING_TYPE (enumtype)))
+ error ("enumerator value %E is outside the range of underlying "
+ "type %<%T%>", value, ENUM_UNDERLYING_TYPE (enumtype));
- /* Silently convert the value so that we can continue. */
- value = perform_implicit_conversion (ENUM_UNDERLYING_TYPE (enumtype),
- value, tf_none);
+ /* Convert the value to the appropriate type. */
+ value = convert (ENUM_UNDERLYING_TYPE (enumtype), value);
}
}
error_mark_node if the function has never been defined, or
a BLOCK if the function has been defined somewhere. */
-void
+bool
start_preparsed_function (tree decl1, tree attrs, int flags)
{
tree ctype = NULL_TREE;
bool honor_interface;
/* Sanity check. */
- gcc_assert (TREE_CODE (TREE_VALUE (void_list_node)) == VOID_TYPE);
+ gcc_assert (VOID_TYPE_P (TREE_VALUE (void_list_node)));
gcc_assert (TREE_CHAIN (void_list_node) == NULL_TREE);
fntype = TREE_TYPE (decl1);
/* Effective C++ rule 15. */
if (warn_ecpp
&& DECL_OVERLOADED_OPERATOR_P (decl1) == NOP_EXPR
- && TREE_CODE (TREE_TYPE (fntype)) == VOID_TYPE)
+ && VOID_TYPE_P (TREE_TYPE (fntype)))
warning (OPT_Weffc__, "%<operator=%> should return a reference to %<*this%>");
/* Make the init_value nonzero so pushdecl knows this is not tentative.
by push_nested_class.) */
if (processing_template_decl)
{
- /* FIXME: Handle error_mark_node more gracefully. */
tree newdecl1 = push_template_decl (decl1);
- if (newdecl1 != error_mark_node)
- decl1 = newdecl1;
+ if (newdecl1 == error_mark_node)
+ {
+ if (ctype || DECL_STATIC_FUNCTION_P (decl1))
+ pop_nested_class ();
+ return false;
+ }
+ decl1 = newdecl1;
}
/* We are now in the scope of the function being defined. */
DECL_CONTEXT (decl1) = DECL_CONTEXT (DECL_TI_TEMPLATE (decl1));
}
fntype = TREE_TYPE (decl1);
+ restype = TREE_TYPE (fntype);
/* If #pragma weak applies, mark the decl appropriately now.
The pragma only applies to global functions. Because
/* This function may already have been parsed, in which case just
return; our caller will skip over the body without parsing. */
if (DECL_INITIAL (decl1) != error_mark_node)
- return;
+ return true;
/* Initialize RTL machinery. We cannot do this until
CURRENT_FUNCTION_DECL and DECL_RESULT are set up. We do this
tree t = DECL_ARGUMENTS (decl1);
gcc_assert (t != NULL_TREE && TREE_CODE (t) == PARM_DECL);
- gcc_assert (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE);
+ gcc_assert (TYPE_PTR_P (TREE_TYPE (t)));
cp_function_chain->x_current_class_ref
= cp_build_indirect_ref (t, RO_NULL, tf_warning_or_error);
start_fname_decls ();
store_parm_decls (current_function_parms);
+
+ return true;
}
/* Like start_preparsed_function, except that instead of a
FUNCTION_DECL, this function takes DECLSPECS and DECLARATOR.
- Returns 1 on success. If the DECLARATOR is not suitable for a function
- (it defines a datum instead), we return 0, which tells
- yyparse to report a parse error. */
+ Returns true on success. If the DECLARATOR is not suitable
+ for a function, we return false, which tells the parser to
+ skip the entire function. */
-int
+bool
start_function (cp_decl_specifier_seq *declspecs,
const cp_declarator *declarator,
tree attrs)
decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, &attrs);
if (decl1 == error_mark_node)
- return 0;
+ 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 0;
+ return false;
}
if (DECL_MAIN_P (decl1))
gcc_assert (same_type_p (TREE_TYPE (TREE_TYPE (decl1)),
integer_type_node));
- start_preparsed_function (decl1, attrs, /*flags=*/SF_DEFAULT);
-
- return 1;
+ return start_preparsed_function (decl1, attrs, /*flags=*/SF_DEFAULT);
}
\f
/* Returns true iff an EH_SPEC_BLOCK should be created in the body of
if (TREE_CODE (parm) == PARM_DECL)
{
if (DECL_NAME (parm) == NULL_TREE
- || TREE_CODE (parm) != VOID_TYPE)
+ || !VOID_TYPE_P (parm))
pushdecl (parm);
else
error ("parameter %qD declared void", parm);
initialize_vtbl_ptrs (current_class_ptr);
finish_compound_stmt (compound_stmt);
+ /* Insert a cleanup to let the back end know that the object is dead
+ when we exit the destructor, either normally or via exception. */
+ tree clobber = build_constructor (current_class_type, NULL);
+ TREE_THIS_VOLATILE (clobber) = true;
+ tree exprstmt = build2 (MODIFY_EXPR, current_class_type,
+ current_class_ref, clobber);
+ finish_decl_cleanup (NULL_TREE, exprstmt);
+
/* And insert cleanups for our bases and members so that they
will be properly destroyed if we throw. */
push_base_cleanups ();
/* Complain if there's just no return statement. */
if (warn_return_type
- && TREE_CODE (TREE_TYPE (fntype)) != VOID_TYPE
+ && !VOID_TYPE_P (TREE_TYPE (fntype))
&& !dependent_type_p (TREE_TYPE (fntype))
&& !current_function_returns_value && !current_function_returns_null
/* Don't complain if we abort or throw. */
\f
/* VAR is a VAR_DECL. If its type is incomplete, remember VAR so that
- we can lay it out later, when and if its type becomes complete. */
+ we can lay it out later, when and if its type becomes complete.
+
+ Also handle constexpr pointer to member variables where the initializer
+ is an unlowered PTRMEM_CST because the class isn't complete yet. */
void
maybe_register_incomplete_var (tree var)
{
- gcc_assert (TREE_CODE (var) == VAR_DECL);
+ gcc_assert (VAR_P (var));
/* Keep track of variables with incomplete types. */
if (!processing_template_decl && TREE_TYPE (var) != error_mark_node
incomplete_var iv = {var, inner_type};
vec_safe_push (incomplete_vars, iv);
}
+ else if (TYPE_PTRMEM_P (inner_type)
+ && DECL_INITIAL (var)
+ && TREE_CODE (DECL_INITIAL (var)) == PTRMEM_CST)
+ {
+ tree context = TYPE_PTRMEM_CLASS_TYPE (inner_type);
+ gcc_assert (TYPE_BEING_DEFINED (context));
+ incomplete_var iv = {var, context};
+ vec_safe_push (incomplete_vars, iv);
+ }
}
}
{
tree var = iv->decl;
tree type = TREE_TYPE (var);
- /* Complete the type of the variable. The VAR_DECL itself
- will be laid out in expand_expr. */
- complete_type (type);
- cp_apply_type_quals_to_decl (cp_type_quals (type), var);
+
+ if (TYPE_PTRMEM_P (type))
+ DECL_INITIAL (var) = cplus_expand_constant (DECL_INITIAL (var));
+ else
+ {
+ /* Complete the type of the variable. The VAR_DECL itself
+ will be laid out in expand_expr. */
+ complete_type (type);
+ cp_apply_type_quals_to_decl (cp_type_quals (type), var);
+ }
+
/* Remove this entry from the list. */
incomplete_vars->unordered_remove (ix);
}
}
/* Handle ordinary C++ destructors. */
type = TREE_TYPE (decl);
- if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+ if (type_build_dtor_call (type))
{
- int flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR;
- bool has_vbases = (TREE_CODE (type) == RECORD_TYPE
- && CLASSTYPE_VBASECLASSES (type));
+ int flags = LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR;
tree addr;
tree call;
else
addr = build_address (decl);
- /* Optimize for space over speed here. */
- if (!has_vbases || flag_expensive_optimizations)
- flags |= LOOKUP_NONVIRTUAL;
-
call = build_delete (TREE_TYPE (addr), addr,
sfk_complete_destructor, flags, 0, complain);
if (call == error_mark_node)
cleanup = error_mark_node;
+ else if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
+ /* Discard the call. */;
else if (cleanup)
cleanup = cp_build_compound_expr (cleanup, call, complain);
else
}
\f
-/* When a stmt has been parsed, this function is called. */
-
-void
-finish_stmt (void)
-{
-}
-
/* Return the FUNCTION_TYPE that corresponds to MEMFNTYPE, which can be a
FUNCTION_DECL, METHOD_TYPE, FUNCTION_TYPE, pointer or reference to
METHOD_TYPE or FUNCTION_TYPE, or pointer to member function. */
return memfntype;
gcc_assert (TREE_CODE (memfntype) == METHOD_TYPE);
args = TYPE_ARG_TYPES (memfntype);
+ cp_ref_qualifier rqual = type_memfn_rqual (memfntype);
fntype = build_function_type (TREE_TYPE (memfntype), TREE_CHAIN (args));
- fntype = apply_memfn_quals (fntype, type_memfn_quals (memfntype));
+ fntype = apply_memfn_quals (fntype, type_memfn_quals (memfntype), rqual);
fntype = (cp_build_type_attribute_variant
(fntype, TYPE_ATTRIBUTES (memfntype)));
fntype = (build_exception_variant
{
tree stype = static_fn_type (decl);
cp_cv_quals quals = type_memfn_quals (stype);
+ cp_ref_qualifier rqual = type_memfn_rqual (stype);
- if (quals != TYPE_UNQUALIFIED)
- stype = apply_memfn_quals (stype, TYPE_UNQUALIFIED);
+ if (quals != TYPE_UNQUALIFIED || rqual != REF_QUAL_NONE)
+ stype = apply_memfn_quals (stype, TYPE_UNQUALIFIED, REF_QUAL_NONE);
TREE_TYPE (decl) = stype;
/* Virtual tables, construction virtual tables, and virtual table
tables all go in a single COMDAT group, named after the primary
virtual table. */
- if (TREE_CODE (decl) == VAR_DECL && DECL_VTABLE_OR_VTT_P (decl))
+ if (VAR_P (decl) && DECL_VTABLE_OR_VTT_P (decl))
name = DECL_ASSEMBLER_NAME (CLASSTYPE_VTABLES (DECL_CONTEXT (decl)));
/* For all other DECLs, the COMDAT group is the mangled name of the
declaration itself. */
return name;
}
+/* Returns the return type for FN as written by the user, which may include
+ a placeholder for a deduced return type. */
+
+tree
+fndecl_declared_return_type (tree fn)
+{
+ 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 TREE_TYPE (TREE_TYPE (fn));
+}
+
+/* Returns true iff DECL was declared with an auto return type and it has
+ not yet been deduced to a real type. */
+
+bool
+undeduced_auto_decl (tree decl)
+{
+ if (cxx_dialect < cxx1y)
+ return false;
+ return type_uses_auto (TREE_TYPE (decl));
+}
+
+/* Complain if DECL has an undeduced return type. */
+
+void
+require_deduced_type (tree decl)
+{
+ if (undeduced_auto_decl (decl))
+ error ("use of %qD before deduction of %<auto%>", decl);
+}
+
#include "gt-cp-decl.h"