aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/backend
diff options
context:
space:
mode:
authorFaisal Abbas <90.abbasfaisal@gmail.com>2022-07-11 15:59:56 +0100
committerPhilip Herron <philip.herron@embecosm.com>2022-08-25 12:40:24 +0100
commita5b583d021a4cbbfafecc28445709afe32cdd1c8 (patch)
tree4eb31564b06a0ea1a9ff677fc2a5d8fe7ee57782 /gcc/rust/backend
parent3343535fdb7fc36e68949a8642d7e67668b67f6c (diff)
downloadgcc-a5b583d021a4cbbfafecc28445709afe32cdd1c8.zip
gcc-a5b583d021a4cbbfafecc28445709afe32cdd1c8.tar.gz
gcc-a5b583d021a4cbbfafecc28445709afe32cdd1c8.tar.bz2
gccrs const folding port: continue porting potential_constant_expression_1()
Following functions are ported in this changeset: - next_initializable_field - sufficient_parms_p - default_ctor_p - user_provided_p - type_has_non_user_provided_default_constructor - default_init_uninitialized_part - extract_conversion_operator - get_class_binding_direct - lang_check_failed - skip_artificial_parms_for - in_class_defaulted_default_constructor - is_instantiation_of_constexpr - check_for_uninitialized_const_var Signed-off-by: Faisal Abbas <90.abbasfaisal@gmail.com>
Diffstat (limited to 'gcc/rust/backend')
-rw-r--r--gcc/rust/backend/rust-tree.cc362
-rw-r--r--gcc/rust/backend/rust-tree.h161
2 files changed, 506 insertions, 17 deletions
diff --git a/gcc/rust/backend/rust-tree.cc b/gcc/rust/backend/rust-tree.cc
index 4439dea..52dae39 100644
--- a/gcc/rust/backend/rust-tree.cc
+++ b/gcc/rust/backend/rust-tree.cc
@@ -23,6 +23,9 @@
#include "escaped_string.h"
#include "libiberty.h"
#include "stor-layout.h"
+#include "hash-map.h"
+#include "diagnostic.h"
+#include "timevar.h"
namespace Rust {
@@ -1134,9 +1137,7 @@ ovl_make (tree fn, tree next)
if (TREE_CODE (fn) == OVERLOAD)
OVL_NESTED_P (result) = true;
- TREE_TYPE (result)
- = (next || TREE_CODE (fn) == TEMPLATE_DECL ? unknown_type_node
- : TREE_TYPE (fn));
+ TREE_TYPE (result) = (next ? unknown_type_node : TREE_TYPE (fn));
if (next && TREE_CODE (next) == OVERLOAD && OVL_DEDUP_P (next))
OVL_DEDUP_P (result) = true;
OVL_FUNCTION (result) = fn;
@@ -1154,13 +1155,7 @@ lookup_add (tree fns, tree lookup)
if (fns == error_mark_node || lookup == error_mark_node)
return error_mark_node;
- if (lookup || TREE_CODE (fns) == TEMPLATE_DECL)
- {
- lookup = ovl_make (fns, lookup);
- OVL_LOOKUP_P (lookup) = true;
- }
- else
- lookup = fns;
+ lookup = fns;
return lookup;
}
@@ -1655,10 +1650,6 @@ called_fns_equal (tree t1, tree t2)
!= DECL_CONTEXT (get_first_fn (t2))))
return false;
- if (TREE_CODE (t1) == TEMPLATE_ID_EXPR)
- targs1 = TREE_OPERAND (t1, 1);
- if (TREE_CODE (t2) == TEMPLATE_ID_EXPR)
- targs2 = TREE_OPERAND (t2, 1);
return rs_tree_equal (targs1, targs2);
}
else
@@ -2421,7 +2412,6 @@ rs_build_qualified_type_real (tree type, int type_quals,
/* A restrict-qualified type must be a pointer (or reference)
to object or incomplete type. */
if ((type_quals & TYPE_QUAL_RESTRICT)
- && TREE_CODE (type) != TEMPLATE_TYPE_PARM
&& TREE_CODE (type) != TYPENAME_TYPE && !INDIRECT_TYPE_P (type))
{
bad_quals |= TYPE_QUAL_RESTRICT;
@@ -2822,4 +2812,346 @@ comptypes (tree t1, tree t2, int strict)
return structural_comptypes (t1, t2, strict);
}
+// forked from gcc/cp/decl.cc next_initializable_field
+
+/* FIELD is an element of TYPE_FIELDS or NULL. In the former case, the value
+ returned is the next FIELD_DECL (possibly FIELD itself) that can be
+ initialized. If there are no more such fields, the return value
+ will be NULL. */
+
+tree
+next_initializable_field (tree field)
+{
+ while (field
+ && (TREE_CODE (field) != FIELD_DECL || DECL_UNNAMED_BIT_FIELD (field)
+ || (DECL_ARTIFICIAL (field)
+ /* Don't skip vptr fields. We might see them when we're
+ called from reduced_constant_expression_p. */
+ && !DECL_VIRTUAL_P (field))))
+ field = DECL_CHAIN (field);
+
+ return field;
+}
+
+// forked from gcc/cp/call.cc sufficient_parms_p
+
+/* Returns nonzero if PARMLIST consists of only default parms,
+ ellipsis, and/or undeduced parameter packs. */
+
+bool
+sufficient_parms_p (const_tree parmlist)
+{
+ for (; parmlist && parmlist != void_list_node;
+ parmlist = TREE_CHAIN (parmlist))
+ if (!TREE_PURPOSE (parmlist))
+ return false;
+ return true;
+}
+
+// forked from gcc/cp/class.cc default_ctor_p
+
+/* Returns true if FN is a default constructor. */
+
+bool
+default_ctor_p (const_tree fn)
+{
+ return (DECL_CONSTRUCTOR_P (fn)
+ && sufficient_parms_p (FUNCTION_FIRST_USER_PARMTYPE (fn)));
+}
+
+// forked from gcc/cp/class.cc user_provided_p
+
+/* Returns true iff FN is a user-provided function, i.e. user-declared
+ and not defaulted at its first declaration. */
+
+bool
+user_provided_p (tree fn)
+{
+ return (!DECL_ARTIFICIAL (fn)
+ && !(DECL_INITIALIZED_IN_CLASS_P (fn)
+ && (DECL_DEFAULTED_FN (fn) || DECL_DELETED_FN (fn))));
+}
+
+// forked from gcc/cp/class.cc type_has_non_user_provided_default_constructor
+
+/* Returns true iff class T has a non-user-provided (i.e. implicitly
+ declared or explicitly defaulted in the class body) default
+ constructor. */
+
+bool
+type_has_non_user_provided_default_constructor (tree t)
+{
+ if (!TYPE_HAS_DEFAULT_CONSTRUCTOR (t))
+ return false;
+ if (CLASSTYPE_LAZY_DEFAULT_CTOR (t))
+ return true;
+
+ for (ovl_iterator iter (CLASSTYPE_CONSTRUCTORS (t)); iter; ++iter)
+ {
+ tree fn = *iter;
+ if (TREE_CODE (fn) == FUNCTION_DECL && default_ctor_p (fn)
+ && !user_provided_p (fn))
+ return true;
+ }
+
+ return false;
+}
+
+// forked from gcc/cp/class.cc default_init_uninitialized_part
+
+/* If default-initialization leaves part of TYPE uninitialized, returns
+ a DECL for the field or TYPE itself (DR 253). */
+
+tree
+default_init_uninitialized_part (tree type)
+{
+ tree t, r, binfo;
+ int i;
+
+ type = strip_array_types (type);
+ if (!CLASS_TYPE_P (type))
+ return type;
+ if (!type_has_non_user_provided_default_constructor (type))
+ return NULL_TREE;
+ for (binfo = TYPE_BINFO (type), i = 0; BINFO_BASE_ITERATE (binfo, i, t); ++i)
+ {
+ r = default_init_uninitialized_part (BINFO_TYPE (t));
+ if (r)
+ return r;
+ }
+ for (t = next_initializable_field (TYPE_FIELDS (type)); t;
+ t = next_initializable_field (DECL_CHAIN (t)))
+ if (!DECL_INITIAL (t) && !DECL_ARTIFICIAL (t))
+ {
+ r = default_init_uninitialized_part (TREE_TYPE (t));
+ if (r)
+ return DECL_P (r) ? r : t;
+ }
+
+ return NULL_TREE;
+}
+
+// forked from gcc/cp/name-lookup.cc extract_conversion_operator
+
+/* FNS is an overload set of conversion functions. Return the
+ overloads converting to TYPE. */
+
+static tree
+extract_conversion_operator (tree fns, tree type)
+{
+ tree convs = NULL_TREE;
+ tree tpls = NULL_TREE;
+
+ for (ovl_iterator iter (fns); iter; ++iter)
+ {
+ if (same_type_p (DECL_CONV_FN_TYPE (*iter), type))
+ convs = lookup_add (*iter, convs);
+ }
+
+ if (!convs)
+ convs = tpls;
+
+ return convs;
+}
+
+// forked from gcc/cp/name-lookup.cc
+
+/* Look for NAME as an immediate member of KLASS (including
+ anon-members or unscoped enum member). TYPE_OR_FNS is zero for
+ regular search. >0 to get a type binding (if there is one) and <0
+ if you want (just) the member function binding.
+
+ Use this if you do not want lazy member creation. */
+
+tree
+get_class_binding_direct (tree klass, tree name, bool want_type)
+{
+ gcc_checking_assert (RECORD_OR_UNION_TYPE_P (klass));
+
+ /* Conversion operators can only be found by the marker conversion
+ operator name. */
+ bool conv_op = IDENTIFIER_CONV_OP_P (name);
+ tree lookup = conv_op ? conv_op_identifier : name;
+ tree val = NULL_TREE;
+ vec<tree, va_gc> *member_vec = CLASSTYPE_MEMBER_VEC (klass);
+
+ if (COMPLETE_TYPE_P (klass) && member_vec)
+ {
+ val = member_vec_binary_search (member_vec, lookup);
+ if (!val)
+ ;
+ else if (STAT_HACK_P (val))
+ val = want_type ? STAT_TYPE (val) : STAT_DECL (val);
+ else if (want_type && !DECL_DECLARES_TYPE_P (val))
+ val = NULL_TREE;
+ }
+ else
+ {
+ if (member_vec && !want_type)
+ val = member_vec_linear_search (member_vec, lookup);
+
+ if (!val || (TREE_CODE (val) == OVERLOAD && OVL_DEDUP_P (val)))
+ /* Dependent using declarations are a 'field', make sure we
+ return that even if we saw an overload already. */
+ if (tree field_val = fields_linear_search (klass, lookup, want_type))
+ {
+ if (!val)
+ val = field_val;
+ else if (TREE_CODE (field_val) == USING_DECL)
+ val = ovl_make (field_val, val);
+ }
+ }
+
+ /* Extract the conversion operators asked for, unless the general
+ conversion operator was requested. */
+ if (val && conv_op)
+ {
+ gcc_checking_assert (OVL_FUNCTION (val) == conv_op_marker);
+ val = OVL_CHAIN (val);
+ if (tree type = TREE_TYPE (name))
+ val = extract_conversion_operator (val, type);
+ }
+
+ return val;
+}
+
+#if defined ENABLE_TREE_CHECKING
+
+// forked from gcc/cp/tree.cc lang_check_failed
+
+/* Complain that some language-specific thing hanging off a tree
+ node has been accessed improperly. */
+
+void
+lang_check_failed (const char *file, int line, const char *function)
+{
+ internal_error ("%<lang_*%> check: failed in %s, at %s:%d", function,
+ trim_filename (file), line);
+}
+#endif /* ENABLE_TREE_CHECKING */
+
+// forked from gcc/cp/tree.cc skip_artificial_parms_for
+
+/* Given a FUNCTION_DECL FN and a chain LIST, skip as many elements of LIST
+ as there are artificial parms in FN. */
+
+tree
+skip_artificial_parms_for (const_tree fn, tree list)
+{
+ if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
+ list = TREE_CHAIN (list);
+ else
+ return list;
+
+ if (DECL_HAS_IN_CHARGE_PARM_P (fn))
+ list = TREE_CHAIN (list);
+ if (DECL_HAS_VTT_PARM_P (fn))
+ list = TREE_CHAIN (list);
+ return list;
+}
+
+// forked from gcc/cp/class.cc in_class_defaulted_default_constructor
+
+/* Returns the defaulted constructor if T has one. Otherwise, returns
+ NULL_TREE. */
+
+tree
+in_class_defaulted_default_constructor (tree t)
+{
+ if (!TYPE_HAS_USER_CONSTRUCTOR (t))
+ return NULL_TREE;
+
+ for (ovl_iterator iter (CLASSTYPE_CONSTRUCTORS (t)); iter; ++iter)
+ {
+ tree fn = *iter;
+
+ if (DECL_DEFAULTED_IN_CLASS_P (fn) && default_ctor_p (fn))
+ return fn;
+ }
+
+ return NULL_TREE;
+}
+
+// forked from gcc/cp/constexpr.cc
+
+/* Returns true iff FUN is an instantiation of a constexpr function
+ template or a defaulted constexpr function. */
+
+bool
+is_instantiation_of_constexpr (tree fun)
+{
+ return ((DECL_DEFAULTED_FN (fun) && DECL_DECLARED_CONSTEXPR_P (fun)));
+}
+
+// forked from gcc/cp/decl.cc check_for_uninitialized_const_var
+
+/* Issue an error message if DECL is an uninitialized const variable.
+ CONSTEXPR_CONTEXT_P is true when the function is called in a constexpr
+ context from potential_constant_expression. Returns true if all is well,
+ false otherwise. */
+
+bool
+check_for_uninitialized_const_var (tree decl, bool constexpr_context_p,
+ tsubst_flags_t complain)
+{
+ tree type = strip_array_types (TREE_TYPE (decl));
+
+ /* ``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 (VAR_P (decl) && !TYPE_REF_P (type) && (RS_TYPE_CONST_P (type))
+ && !DECL_NONTRIVIALLY_INITIALIZED_P (decl))
+ {
+ tree field = default_init_uninitialized_part (type);
+ if (!field)
+ return true;
+
+ bool show_notes = true;
+
+ if (!constexpr_context_p)
+ {
+ if (RS_TYPE_CONST_P (type))
+ {
+ if (complain & tf_error)
+ show_notes = permerror (DECL_SOURCE_LOCATION (decl),
+ "uninitialized %<const %D%>", decl);
+ }
+ else
+ {
+ if (!is_instantiation_of_constexpr (current_function_decl)
+ && (complain & tf_error))
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "uninitialized variable %qD in %<constexpr%> "
+ "function",
+ decl);
+ else
+ show_notes = false;
+ }
+ }
+ else if (complain & tf_error)
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "uninitialized variable %qD in %<constexpr%> context", decl);
+
+ if (show_notes && CLASS_TYPE_P (type) && (complain & tf_error))
+ {
+ tree defaulted_ctor;
+
+ inform (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (type)),
+ "%q#T has no user-provided default constructor", type);
+ defaulted_ctor = in_class_defaulted_default_constructor (type);
+ if (defaulted_ctor)
+ inform (DECL_SOURCE_LOCATION (defaulted_ctor),
+ "constructor is not user-provided because it is "
+ "explicitly defaulted in the class body");
+ inform (DECL_SOURCE_LOCATION (field),
+ "and the implicitly-defined constructor does not "
+ "initialize %q#D",
+ field);
+ }
+
+ return false;
+ }
+
+ return true;
+}
} // namespace Rust
diff --git a/gcc/rust/backend/rust-tree.h b/gcc/rust/backend/rust-tree.h
index d5cc318..b838e40 100644
--- a/gcc/rust/backend/rust-tree.h
+++ b/gcc/rust/backend/rust-tree.h
@@ -763,8 +763,6 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX];
level 2. */
#define DECL_PARM_LEVEL(NODE) (LANG_DECL_PARM_CHECK (NODE)->level)
-#define LANG_DECL_PARM_CHECK(NODE) (&DECL_LANG_SPECIFIC (NODE)->u.parm)
-
/* These flags are used by the conversion code.
CONV_IMPLICIT : Perform implicit conversions (standard and user-defined).
CONV_STATIC : Perform the explicit conversions for static_cast.
@@ -845,6 +843,133 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX];
/* Returns true if NODE is a pointer-to-data-member. */
#define TYPE_PTRDATAMEM_P(NODE) (TREE_CODE (NODE) == OFFSET_TYPE)
+/* Nonzero if this type is const-qualified. */
+#define RS_TYPE_CONST_P(NODE) ((rs_type_quals (NODE) & TYPE_QUAL_CONST) != 0)
+
+/* The _DECL for this _TYPE. */
+#define TYPE_MAIN_DECL(NODE) (TYPE_STUB_DECL (TYPE_MAIN_VARIANT (NODE)))
+
+/* Nonzero for a VAR_DECL iff an explicit initializer was provided
+ or a non-trivial constructor is called. */
+#define DECL_NONTRIVIALLY_INITIALIZED_P(NODE) \
+ (TREE_LANG_FLAG_6 (VAR_DECL_CHECK (NODE)))
+
+/* Nonzero if DECL was declared with '= default' (maybe implicitly). */
+#define DECL_DEFAULTED_FN(DECL) (LANG_DECL_FN_CHECK (DECL)->defaulted_p)
+
+/* Nonzero for a class type means that the class type has a
+ user-declared constructor. */
+#define TYPE_HAS_USER_CONSTRUCTOR(NODE) (TYPE_LANG_FLAG_1 (NODE))
+
+/* A FUNCTION_DECL or OVERLOAD for the constructors for NODE. These
+ are the constructors that take an in-charge parameter. */
+#define CLASSTYPE_CONSTRUCTORS(NODE) \
+ (get_class_binding_direct (NODE, ctor_identifier))
+
+/* Nonzero if the DECL was initialized in the class definition itself,
+ rather than outside the class. This is used for both static member
+ VAR_DECLS, and FUNCTION_DECLS that are defined in the class. */
+#define DECL_INITIALIZED_IN_CLASS_P(DECL) \
+ (DECL_LANG_SPECIFIC (VAR_OR_FUNCTION_DECL_CHECK (DECL)) \
+ ->u.base.initialized_in_class)
+
+/* Nonzero if DECL is explicitly defaulted in the class body. */
+#define DECL_DEFAULTED_IN_CLASS_P(DECL) \
+ (DECL_DEFAULTED_FN (DECL) && DECL_INITIALIZED_IN_CLASS_P (DECL))
+
+/* Nonzero for FUNCTION_DECL means that this decl is a non-static
+ member function. */
+#define DECL_NONSTATIC_MEMBER_FUNCTION_P(NODE) \
+ (TREE_CODE (TREE_TYPE (NODE)) == METHOD_TYPE)
+
+/* For FUNCTION_DECLs: nonzero means that this function is a
+ constructor or a destructor with an extra in-charge parameter to
+ control whether or not virtual bases are constructed. */
+#define DECL_HAS_IN_CHARGE_PARM_P(NODE) \
+ (LANG_DECL_FN_CHECK (NODE)->has_in_charge_parm_p)
+
+/* Nonzero if the VTT parm has been added to NODE. */
+#define DECL_HAS_VTT_PARM_P(NODE) (LANG_DECL_FN_CHECK (NODE)->has_vtt_parm_p)
+
+/* Given a FUNCTION_DECL, returns the first TREE_LIST out of TYPE_ARG_TYPES
+ which refers to a user-written parameter. */
+#define FUNCTION_FIRST_USER_PARMTYPE(NODE) \
+ skip_artificial_parms_for ((NODE), TYPE_ARG_TYPES (TREE_TYPE (NODE)))
+
+/* Similarly, but for DECL_ARGUMENTS. */
+#define FUNCTION_FIRST_USER_PARM(NODE) \
+ skip_artificial_parms_for ((NODE), DECL_ARGUMENTS (NODE))
+
+/* For FUNCTION_DECLs and TEMPLATE_DECLs: nonzero means that this function
+ is a constructor. */
+#define DECL_CONSTRUCTOR_P(NODE) DECL_CXX_CONSTRUCTOR_P (NODE)
+
+/* Nonzero if DECL was declared with '= delete'. */
+#define DECL_DELETED_FN(DECL) \
+ (LANG_DECL_FN_CHECK (DECL)->min.base.threadprivate_or_deleted_p)
+
+/* Nonzero if DECL was declared with '= default' (maybe implicitly). */
+#define DECL_DEFAULTED_FN(DECL) (LANG_DECL_FN_CHECK (DECL)->defaulted_p)
+
+#if defined ENABLE_TREE_CHECKING
+
+#define LANG_DECL_MIN_CHECK(NODE) \
+ __extension__({ \
+ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \
+ if (!LANG_DECL_HAS_MIN (NODE)) \
+ lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \
+ &lt->u.min; \
+ })
+
+/* We want to be able to check DECL_CONSTRUCTOR_P and such on a function
+ template, not just on a FUNCTION_DECL. So when looking for things in
+ lang_decl_fn, look down through a TEMPLATE_DECL into its result. */
+#define LANG_DECL_FN_CHECK(NODE) \
+ __extension__({ \
+ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \
+ if (!DECL_DECLARES_FUNCTION_P (NODE) || lt->u.base.selector != lds_fn) \
+ lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \
+ &lt->u.fn; \
+ })
+
+#define LANG_DECL_NS_CHECK(NODE) \
+ __extension__({ \
+ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \
+ if (TREE_CODE (NODE) != NAMESPACE_DECL || lt->u.base.selector != lds_ns) \
+ lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \
+ &lt->u.ns; \
+ })
+
+#define LANG_DECL_PARM_CHECK(NODE) \
+ __extension__({ \
+ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \
+ if (TREE_CODE (NODE) != PARM_DECL || lt->u.base.selector != lds_parm) \
+ lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \
+ &lt->u.parm; \
+ })
+
+#define LANG_DECL_DECOMP_CHECK(NODE) \
+ __extension__({ \
+ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \
+ if (!VAR_P (NODE) || lt->u.base.selector != lds_decomp) \
+ lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \
+ &lt->u.decomp; \
+ })
+
+#else
+
+#define LANG_DECL_MIN_CHECK(NODE) (&DECL_LANG_SPECIFIC (NODE)->u.min)
+
+#define LANG_DECL_FN_CHECK(NODE) (&DECL_LANG_SPECIFIC (NODE)->u.fn)
+
+#define LANG_DECL_NS_CHECK(NODE) (&DECL_LANG_SPECIFIC (NODE)->u.ns)
+
+#define LANG_DECL_PARM_CHECK(NODE) (&DECL_LANG_SPECIFIC (NODE)->u.parm)
+
+#define LANG_DECL_DECOMP_CHECK(NODE) (&DECL_LANG_SPECIFIC (NODE)->u.decomp)
+
+#endif /* ENABLE_TREE_CHECKING */
+
// Below macros are copied from gcc/c-family/c-common.h
/* In a FIELD_DECL, nonzero if the decl was originally a bitfield. */
@@ -1744,6 +1869,38 @@ extern bool same_type_ignoring_top_level_qualifiers_p (tree, tree);
extern bool comp_ptr_ttypes_const (tree, tree, compare_bounds_t);
+extern tree
+get_class_binding_direct (tree, tree, bool want_type = false);
+
+extern tree skip_artificial_parms_for (const_tree, tree);
+
+extern void
+lang_check_failed (const char *, int,
+ const char *) ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
+
+extern tree default_init_uninitialized_part (tree);
+
+extern bool type_has_non_user_provided_default_constructor (tree);
+
+extern bool default_ctor_p (const_tree);
+
+extern bool user_provided_p (tree);
+
+extern bool sufficient_parms_p (const_tree);
+
+extern tree next_initializable_field (tree);
+
+extern tree in_class_defaulted_default_constructor (tree);
+
+extern bool is_instantiation_of_constexpr (tree);
+
+extern bool
+check_for_uninitialized_const_var (tree, bool, tsubst_flags_t);
+
+extern bool reduced_constant_expression_p (tree);
+
+extern tree cv_unqualified (tree);
+
// forked from gcc/cp/cp-tree.h
enum