aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/backend
diff options
context:
space:
mode:
authorFaisal Abbas <90.abbasfaisal@gmail.com>2022-07-18 16:07:22 +0100
committerPhilip Herron <philip.herron@embecosm.com>2022-08-25 12:40:24 +0100
commita00b61e6bfc4a79af55236db0e602e09cd8fda72 (patch)
tree372b21fad7406485934f78a8d48c682901a9d832 /gcc/rust/backend
parent7c13a2e5873f5919c00b5f37b6db52af8d0f7300 (diff)
downloadgcc-a00b61e6bfc4a79af55236db0e602e09cd8fda72.zip
gcc-a00b61e6bfc4a79af55236db0e602e09cd8fda72.tar.gz
gcc-a00b61e6bfc4a79af55236db0e602e09cd8fda72.tar.bz2
gccrs const folding port: continue porting potential_constant_expression_1()
Following functions are ported in this changeset: - find_heap_var_refs - find_immediate_fndecl - instantiation_dependent_expression_p - cp_get_callee - build_nop - scalarish_type_p - type_has_nontrivial_copy_init - build_local_temp - is_normal_capture_proxy - reject_gcc_builtin - is_bitfield_expr_with_lowered_type - maybe_undo_parenthesized_ref - fold_offsetof - char_type_p - resolve_nondeduced_context - null_node_p Following structs, classes and enums are ported in this changeset: - c_tree_index - warning_sentinel - uid_sensitive_constexpr_evaluation_checker - iloc_sentinel - ptrmem_cst This changeset puts c_global_trees and cp_global_trees outside Rust and Compile namespaces because keeping them inside is causing build issues. This is possibly because rust-tree.cc contains only Rust namespace while rust-constexpr.cc is Rust+Compile namespace. This causes issues when trying to use them inside both files. Signed-off-by: Faisal Abbas <90.abbasfaisal@gmail.com>
Diffstat (limited to 'gcc/rust/backend')
-rw-r--r--gcc/rust/backend/rust-constexpr.cc105
-rw-r--r--gcc/rust/backend/rust-tree.cc501
-rw-r--r--gcc/rust/backend/rust-tree.h304
3 files changed, 899 insertions, 11 deletions
diff --git a/gcc/rust/backend/rust-constexpr.cc b/gcc/rust/backend/rust-constexpr.cc
index 8fb378f..189bada 100644
--- a/gcc/rust/backend/rust-constexpr.cc
+++ b/gcc/rust/backend/rust-constexpr.cc
@@ -25,7 +25,9 @@
#include "print-tree.h"
#include "gimplify.h"
#include "tree-iterator.h"
+#include "timevar.h"
#include "varasm.h"
+#include "cgraph.h"
#define VERIFY_CONSTANT(X) \
do \
@@ -50,6 +52,11 @@ struct constexpr_global_ctx
{
HOST_WIDE_INT constexpr_ops_count;
+ /* Cleanups that need to be evaluated at the end of CLEANUP_POINT_EXPR. */
+ vec<tree> *cleanups;
+ /* Heap VAR_DECLs created during the evaluation of the outermost constant
+ expression. */
+ auto_vec<tree, 16> heap_vars;
constexpr_global_ctx () : constexpr_ops_count (0) {}
};
@@ -481,6 +488,60 @@ var_in_maybe_constexpr_fn (tree t)
// forked from gcc/cp/constexpr.cc array_index_cmp
+/* Some of the expressions fed to the constexpr mechanism are calls to
+ constructors, which have type void. In that case, return the type being
+ initialized by the constructor. */
+
+static tree
+initialized_type (tree t)
+{
+ if (TYPE_P (t))
+ return t;
+ tree type = TREE_TYPE (t);
+ if (TREE_CODE (t) == CALL_EXPR)
+ {
+ /* A constructor call has void type, so we need to look deeper. */
+ tree fn = get_function_named_in_call (t);
+ if (fn && TREE_CODE (fn) == FUNCTION_DECL && DECL_CXX_CONSTRUCTOR_P (fn))
+ type = DECL_CONTEXT (fn);
+ }
+ else if (TREE_CODE (t) == COMPOUND_EXPR)
+ return initialized_type (TREE_OPERAND (t, 1));
+
+ return cv_unqualified (type);
+}
+
+/* P0859: A function is needed for constant evaluation if it is a constexpr
+ function that is named by an expression ([basic.def.odr]) that is
+ potentially constant evaluated.
+
+ So we need to instantiate any constexpr functions mentioned by the
+ expression even if the definition isn't needed for evaluating the
+ expression. */
+
+static tree
+instantiate_cx_fn_r (tree *tp, int *walk_subtrees, void * /*data*/)
+{
+ if (TREE_CODE (*tp) == CALL_EXPR)
+ {
+ if (EXPR_HAS_LOCATION (*tp))
+ input_location = EXPR_LOCATION (*tp);
+ }
+
+ if (!EXPR_P (*tp))
+ *walk_subtrees = 0;
+
+ return NULL_TREE;
+}
+
+static void
+instantiate_constexpr_fns (tree t)
+{
+ location_t loc = input_location;
+ rs_walk_tree_without_duplicates (&t, instantiate_cx_fn_r, NULL);
+ input_location = loc;
+}
+
/* Returns less than, equal to, or greater than zero if KEY is found to be
less than, to match, or to be greater than the constructor_elt's INDEX. */
@@ -508,8 +569,6 @@ array_index_cmp (tree key, tree index)
}
}
-// forked from gcc/cp/constexpr.cc unshare_constructor
-
/* If T is a CONSTRUCTOR, return an unshared copy of T and any
sub-CONSTRUCTORs. Otherwise return T.
@@ -540,8 +599,6 @@ unshare_constructor (tree t MEM_STAT_DECL)
return t;
}
-// forked from gcc/cp/constexpr.cc find_array_ctor_elt
-
/* Returns the index of the constructor_elt of ARY which matches DINDEX, or -1
if none. If INSERT is true, insert a matching element rather than fail. */
@@ -666,8 +723,6 @@ find_array_ctor_elt (tree ary, tree dindex, bool insert)
return -1;
}
-// forked from gcc/cp/constexpr.cc reduced_constant_expression_p
-
/* Return true if T is a valid constant initializer. If a CONSTRUCTOR
initializes all the members, the CONSTRUCTOR_NO_CLEARING flag will be
cleared.
@@ -758,8 +813,6 @@ reduced_constant_expression_p (tree t)
}
}
-// forked from gcc/cp/constexpr.cc verify_constant
-
/* Some expressions may have constant operands but are not constant
themselves, such as 1/0. Call this function to check for that
condition.
@@ -794,6 +847,42 @@ verify_constant (tree t, bool allow_non_constant, bool *non_constant_p,
return *non_constant_p;
}
+// forked from gcc/cp/constexpr.cc find_heap_var_refs
+
+/* Look for heap variables in the expression *TP. */
+
+static tree
+find_heap_var_refs (tree *tp, int *walk_subtrees, void * /*data*/)
+{
+ if (VAR_P (*tp)
+ && (DECL_NAME (*tp) == heap_uninit_identifier
+ || DECL_NAME (*tp) == heap_identifier
+ || DECL_NAME (*tp) == heap_vec_uninit_identifier
+ || DECL_NAME (*tp) == heap_vec_identifier
+ || DECL_NAME (*tp) == heap_deleted_identifier))
+ return *tp;
+
+ if (TYPE_P (*tp))
+ *walk_subtrees = 0;
+ return NULL_TREE;
+}
+
+// forked from gcc/cp/constexpr.cc find_immediate_fndecl
+
+/* Find immediate function decls in *TP if any. */
+
+static tree
+find_immediate_fndecl (tree *tp, int * /*walk_subtrees*/, void * /*data*/)
+{
+ if (TREE_CODE (*tp) == FUNCTION_DECL && DECL_IMMEDIATE_FUNCTION_P (*tp))
+ return *tp;
+ if (TREE_CODE (*tp) == PTRMEM_CST
+ && TREE_CODE (PTRMEM_CST_MEMBER (*tp)) == FUNCTION_DECL
+ && DECL_IMMEDIATE_FUNCTION_P (PTRMEM_CST_MEMBER (*tp)))
+ return PTRMEM_CST_MEMBER (*tp);
+ return NULL_TREE;
+}
+
// forked in gcc/cp/constexpr.cc diag_array_subscript
/* Under the control of CTX, issue a detailed diagnostic for
diff --git a/gcc/rust/backend/rust-tree.cc b/gcc/rust/backend/rust-tree.cc
index 9221f7b..22e91f4 100644
--- a/gcc/rust/backend/rust-tree.cc
+++ b/gcc/rust/backend/rust-tree.cc
@@ -26,6 +26,13 @@
#include "hash-map.h"
#include "diagnostic.h"
#include "timevar.h"
+#include "convert.h"
+#include "gimple-expr.h"
+
+// forked from gcc/c-family/c-common.cc c_global_trees
+tree c_global_trees[CTI_MAX];
+// forked from gcc/cp/decl.cc cp_global_trees
+tree cp_global_trees[CPTI_MAX];
namespace Rust {
@@ -995,7 +1002,115 @@ rs_type_quals (const_tree type)
tree type_info_type_node, tinfo_decl_id, tinfo_decl_type;
tree tinfo_var_id; */
-tree cp_global_trees[CPTI_MAX];
+/* The following symbols are subsumed in the c_global_trees array, and
+ listed here individually for documentation purposes.
+
+ INTEGER_TYPE and REAL_TYPE nodes for the standard data types.
+
+ tree short_integer_type_node;
+ tree long_integer_type_node;
+ tree long_long_integer_type_node;
+
+ tree short_unsigned_type_node;
+ tree long_unsigned_type_node;
+ tree long_long_unsigned_type_node;
+
+ tree truthvalue_type_node;
+ tree truthvalue_false_node;
+ tree truthvalue_true_node;
+
+ tree ptrdiff_type_node;
+
+ tree unsigned_char_type_node;
+ tree signed_char_type_node;
+ tree wchar_type_node;
+
+ tree char8_type_node;
+ tree char16_type_node;
+ tree char32_type_node;
+
+ tree float_type_node;
+ tree double_type_node;
+ tree long_double_type_node;
+
+ tree complex_integer_type_node;
+ tree complex_float_type_node;
+ tree complex_double_type_node;
+ tree complex_long_double_type_node;
+
+ tree dfloat32_type_node;
+ tree dfloat64_type_node;
+ tree_dfloat128_type_node;
+
+ tree intQI_type_node;
+ tree intHI_type_node;
+ tree intSI_type_node;
+ tree intDI_type_node;
+ tree intTI_type_node;
+
+ tree unsigned_intQI_type_node;
+ tree unsigned_intHI_type_node;
+ tree unsigned_intSI_type_node;
+ tree unsigned_intDI_type_node;
+ tree unsigned_intTI_type_node;
+
+ tree widest_integer_literal_type_node;
+ tree widest_unsigned_literal_type_node;
+
+ Nodes for types `void *' and `const void *'.
+
+ tree ptr_type_node, const_ptr_type_node;
+
+ Nodes for types `char *' and `const char *'.
+
+ tree string_type_node, const_string_type_node;
+
+ Type `char[SOMENUMBER]'.
+ Used when an array of char is needed and the size is irrelevant.
+
+ tree char_array_type_node;
+
+ Type `wchar_t[SOMENUMBER]' or something like it.
+ Used when a wide string literal is created.
+
+ tree wchar_array_type_node;
+
+ Type `char8_t[SOMENUMBER]' or something like it.
+ Used when a UTF-8 string literal is created.
+
+ tree char8_array_type_node;
+
+ Type `char16_t[SOMENUMBER]' or something like it.
+ Used when a UTF-16 string literal is created.
+
+ tree char16_array_type_node;
+
+ Type `char32_t[SOMENUMBER]' or something like it.
+ Used when a UTF-32 string literal is created.
+
+ tree char32_array_type_node;
+
+ Type `int ()' -- used for implicit declaration of functions.
+
+ tree default_function_type;
+
+ A VOID_TYPE node, packaged in a TREE_LIST.
+
+ tree void_list_node;
+
+ The lazily created VAR_DECLs for __FUNCTION__, __PRETTY_FUNCTION__,
+ and __func__. (C doesn't generate __FUNCTION__ and__PRETTY_FUNCTION__
+ VAR_DECLS, but C++ does.)
+
+ tree function_name_decl_node;
+ tree pretty_function_name_decl_node;
+ tree c99_function_name_decl_node;
+
+ Stack of nested function name VAR_DECLs.
+
+ tree saved_function_name_decls;
+
+*/
// forked from gcc/cp/module.cc fixed_trees
@@ -1035,6 +1150,7 @@ maybe_add_global (tree val, unsigned &crc)
/* Global trees. */
static const std::pair<tree *, unsigned> global_tree_arys[] = {
std::pair<tree *, unsigned> (cp_global_trees, CPTI_MODULE_HWM),
+ std::pair<tree *, unsigned> (c_global_trees, CTI_MODULE_HWM),
};
// forked from gcc/cp/module.cc init_modules
@@ -1051,6 +1167,13 @@ init_modules ()
{
maybe_add_global (*ptr, crc);
}
+
+ ptr = global_tree_arys[1].first;
+ limit = global_tree_arys[1].second;
+ for (unsigned ix = 0; ix != limit; ix++, ptr++)
+ {
+ maybe_add_global (*ptr, crc);
+ }
}
// forked from gcc/cp/constexpr.cc var_in_constexpr_fn
@@ -3222,4 +3345,380 @@ release_tree_vector (vec<tree, va_gc> *vec)
}
}
}
+
+// forked from gcc/cp/cvt.cc instantiation_dependent_expression_p
+
+/* As above, but also check value-dependence of the expression as a whole. */
+
+bool
+instantiation_dependent_expression_p (tree expression)
+{
+ return false;
+}
+
+// forked from gcc/cp/cvt.cc cp_get_callee
+
+/* If CALL is a call, return the callee; otherwise null. */
+
+tree
+cp_get_callee (tree call)
+{
+ if (call == NULL_TREE)
+ return call;
+ else if (TREE_CODE (call) == CALL_EXPR)
+ return CALL_EXPR_FN (call);
+ return NULL_TREE;
+}
+
+// forked from gcc/cp/typeck.cc build_nop
+
+/* Return a NOP_EXPR converting EXPR to TYPE. */
+
+tree
+build_nop (tree type, tree expr)
+{
+ if (type == error_mark_node || error_operand_p (expr))
+ return expr;
+ return build1_loc (EXPR_LOCATION (expr), NOP_EXPR, type, expr);
+}
+
+// forked from gcc/cp/tree.cc scalarish_type_p
+
+/* Returns 1 iff type T is something we want to treat as a scalar type for
+ the purpose of deciding whether it is trivial/POD/standard-layout. */
+
+bool
+scalarish_type_p (const_tree t)
+{
+ if (t == error_mark_node)
+ return 1;
+
+ return (SCALAR_TYPE_P (t) || VECTOR_TYPE_P (t));
+}
+
+// forked from gcc/cp/tree.cc type_has_nontrivial_copy_init
+
+/* Returns true iff copying an object of type T (including via move
+ constructor) is non-trivial. That is, T has no non-trivial copy
+ constructors and no non-trivial move constructors, and not all copy/move
+ constructors are deleted. This function implements the ABI notion of
+ non-trivial copy, which has diverged from the one in the standard. */
+
+bool
+type_has_nontrivial_copy_init (const_tree type)
+{
+ return false;
+}
+
+// forked from gcc/cp/tree.cc build_local_temp
+
+/* Return an undeclared local temporary of type TYPE for use in building a
+ TARGET_EXPR. */
+
+tree
+build_local_temp (tree type)
+{
+ tree slot = build_decl (input_location, VAR_DECL, NULL_TREE, type);
+ DECL_ARTIFICIAL (slot) = 1;
+ DECL_IGNORED_P (slot) = 1;
+ DECL_CONTEXT (slot) = current_function_decl;
+ layout_decl (slot, 0);
+ return slot;
+}
+
+// forked from gcc/cp/lambda.cc is_normal_capture_proxy
+
+/* Returns true iff DECL is a capture proxy for a normal capture
+ (i.e. without explicit initializer). */
+
+bool
+is_normal_capture_proxy (tree decl)
+{
+ return false;
+}
+
+// forked from gcc/cp/c-common.cc reject_gcc_builtin
+
+/* For an EXPR of a FUNCTION_TYPE that references a GCC built-in function
+ with no library fallback or for an ADDR_EXPR whose operand is such type
+ issues an error pointing to the location LOC.
+ Returns true when the expression has been diagnosed and false
+ otherwise. */
+
+bool
+reject_gcc_builtin (const_tree expr, location_t loc /* = UNKNOWN_LOCATION */)
+{
+ if (TREE_CODE (expr) == ADDR_EXPR)
+ expr = TREE_OPERAND (expr, 0);
+
+ STRIP_ANY_LOCATION_WRAPPER (expr);
+
+ if (TREE_TYPE (expr) && TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE
+ && TREE_CODE (expr) == FUNCTION_DECL
+ /* The intersection of DECL_BUILT_IN and DECL_IS_UNDECLARED_BUILTIN avoids
+ false positives for user-declared built-ins such as abs or
+ strlen, and for C++ operators new and delete.
+ The c_decl_implicit() test avoids false positives for implicitly
+ declared built-ins with library fallbacks (such as abs). */
+ && fndecl_built_in_p (expr) && DECL_IS_UNDECLARED_BUILTIN (expr)
+ && !DECL_ASSEMBLER_NAME_SET_P (expr))
+ {
+ if (loc == UNKNOWN_LOCATION)
+ loc = EXPR_LOC_OR_LOC (expr, input_location);
+
+ /* Reject arguments that are built-in functions with
+ no library fallback. */
+ error_at (loc, "built-in function %qE must be directly called", expr);
+
+ return true;
+ }
+
+ return false;
+}
+
+// forked from gcc/cp/typeck.cc is_bitfield_expr_with_lowered_type
+
+/* If EXP is a reference to a bit-field, and the type of EXP does not
+ match the declared type of the bit-field, return the declared type
+ of the bit-field. Otherwise, return NULL_TREE. */
+
+tree
+is_bitfield_expr_with_lowered_type (const_tree exp)
+{
+ switch (TREE_CODE (exp))
+ {
+ case COND_EXPR:
+ if (!is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 1)
+ ? TREE_OPERAND (exp, 1)
+ : TREE_OPERAND (exp, 0)))
+ return NULL_TREE;
+ return is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 2));
+
+ case COMPOUND_EXPR:
+ return is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 1));
+
+ case MODIFY_EXPR:
+ case SAVE_EXPR:
+ case UNARY_PLUS_EXPR:
+ case PREDECREMENT_EXPR:
+ case PREINCREMENT_EXPR:
+ case POSTDECREMENT_EXPR:
+ case POSTINCREMENT_EXPR:
+ case NEGATE_EXPR:
+ case NON_LVALUE_EXPR:
+ case BIT_NOT_EXPR:
+ return is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 0));
+
+ case COMPONENT_REF: {
+ tree field;
+
+ field = TREE_OPERAND (exp, 1);
+ if (TREE_CODE (field) != FIELD_DECL || !DECL_BIT_FIELD_TYPE (field))
+ return NULL_TREE;
+ if (same_type_ignoring_top_level_qualifiers_p (
+ TREE_TYPE (exp), DECL_BIT_FIELD_TYPE (field)))
+ return NULL_TREE;
+ return DECL_BIT_FIELD_TYPE (field);
+ }
+
+ case VAR_DECL:
+ if (DECL_HAS_VALUE_EXPR_P (exp))
+ return is_bitfield_expr_with_lowered_type (
+ DECL_VALUE_EXPR (CONST_CAST_TREE (exp)));
+ return NULL_TREE;
+
+ case VIEW_CONVERT_EXPR:
+ if (location_wrapper_p (exp))
+ return is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 0));
+ else
+ return NULL_TREE;
+
+ default:
+ return NULL_TREE;
+ }
+}
+
+// forked from gcc/cp/semantics.cc maybe_undo_parenthesized_ref
+
+/* If T is an id-expression obfuscated by force_paren_expr, undo the
+ obfuscation and return the underlying id-expression. Otherwise
+ return T. */
+
+tree
+maybe_undo_parenthesized_ref (tree t)
+{
+ if ((TREE_CODE (t) == PAREN_EXPR || TREE_CODE (t) == VIEW_CONVERT_EXPR)
+ && REF_PARENTHESIZED_P (t))
+ t = TREE_OPERAND (t, 0);
+
+ return t;
+}
+
+// forked from gcc/c-family/c-common.cc fold_offsetof
+
+/* Fold an offsetof-like expression. EXPR is a nested sequence of component
+ references with an INDIRECT_REF of a constant at the bottom; much like the
+ traditional rendering of offsetof as a macro. TYPE is the desired type of
+ the whole expression. Return the folded result. */
+
+tree
+fold_offsetof (tree expr, tree type, enum tree_code ctx)
+{
+ tree base, off, t;
+ tree_code code = TREE_CODE (expr);
+ switch (code)
+ {
+ case ERROR_MARK:
+ return expr;
+
+ case VAR_DECL:
+ error ("cannot apply %<offsetof%> to static data member %qD", expr);
+ return error_mark_node;
+
+ case CALL_EXPR:
+ case TARGET_EXPR:
+ error ("cannot apply %<offsetof%> when %<operator[]%> is overloaded");
+ return error_mark_node;
+
+ case NOP_EXPR:
+ case INDIRECT_REF:
+ if (!TREE_CONSTANT (TREE_OPERAND (expr, 0)))
+ {
+ error ("cannot apply %<offsetof%> to a non constant address");
+ return error_mark_node;
+ }
+ return convert (type, TREE_OPERAND (expr, 0));
+
+ case COMPONENT_REF:
+ base = fold_offsetof (TREE_OPERAND (expr, 0), type, code);
+ if (base == error_mark_node)
+ return base;
+
+ t = TREE_OPERAND (expr, 1);
+ if (DECL_C_BIT_FIELD (t))
+ {
+ error ("attempt to take address of bit-field structure "
+ "member %qD",
+ t);
+ return error_mark_node;
+ }
+ off = size_binop_loc (input_location, PLUS_EXPR, DECL_FIELD_OFFSET (t),
+ size_int (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (t))
+ / BITS_PER_UNIT));
+ break;
+
+ case ARRAY_REF:
+ base = fold_offsetof (TREE_OPERAND (expr, 0), type, code);
+ if (base == error_mark_node)
+ return base;
+
+ t = TREE_OPERAND (expr, 1);
+ STRIP_ANY_LOCATION_WRAPPER (t);
+
+ /* Check if the offset goes beyond the upper bound of the array. */
+ if (TREE_CODE (t) == INTEGER_CST && tree_int_cst_sgn (t) >= 0)
+ {
+ tree upbound = array_ref_up_bound (expr);
+ if (upbound != NULL_TREE && TREE_CODE (upbound) == INTEGER_CST
+ && !tree_int_cst_equal (upbound,
+ TYPE_MAX_VALUE (TREE_TYPE (upbound))))
+ {
+ if (ctx != ARRAY_REF && ctx != COMPONENT_REF)
+ upbound = size_binop (PLUS_EXPR, upbound,
+ build_int_cst (TREE_TYPE (upbound), 1));
+ if (tree_int_cst_lt (upbound, t))
+ {
+ tree v;
+
+ for (v = TREE_OPERAND (expr, 0);
+ TREE_CODE (v) == COMPONENT_REF; v = TREE_OPERAND (v, 0))
+ if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
+ == RECORD_TYPE)
+ {
+ tree fld_chain = DECL_CHAIN (TREE_OPERAND (v, 1));
+ for (; fld_chain; fld_chain = DECL_CHAIN (fld_chain))
+ if (TREE_CODE (fld_chain) == FIELD_DECL)
+ break;
+
+ if (fld_chain)
+ break;
+ }
+ /* Don't warn if the array might be considered a poor
+ man's flexible array member with a very permissive
+ definition thereof. */
+ if (TREE_CODE (v) == ARRAY_REF
+ || TREE_CODE (v) == COMPONENT_REF)
+ warning (OPT_Warray_bounds,
+ "index %E denotes an offset "
+ "greater than size of %qT",
+ t, TREE_TYPE (TREE_OPERAND (expr, 0)));
+ }
+ }
+ }
+
+ t = convert (sizetype, t);
+ off = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (TREE_TYPE (expr)), t);
+ break;
+
+ case COMPOUND_EXPR:
+ /* Handle static members of volatile structs. */
+ t = TREE_OPERAND (expr, 1);
+ gcc_checking_assert (VAR_P (get_base_address (t)));
+ return fold_offsetof (t, type);
+
+ default:
+ gcc_unreachable ();
+ }
+
+ if (!POINTER_TYPE_P (type))
+ return size_binop (PLUS_EXPR, base, convert (type, off));
+ return fold_build_pointer_plus (base, off);
+}
+
+// forked from gcc/cp/tree.cc char_type_p
+
+/* Returns nonzero if TYPE is a character type, including wchar_t. */
+
+int
+char_type_p (tree type)
+{
+ return (same_type_p (type, char_type_node)
+ || same_type_p (type, unsigned_char_type_node)
+ || same_type_p (type, signed_char_type_node)
+ || same_type_p (type, char8_type_node)
+ || same_type_p (type, char16_type_node)
+ || same_type_p (type, char32_type_node)
+ || same_type_p (type, wchar_type_node));
+}
+
+// forked from gcc/cp/pt.cc resolve_nondeduced_context
+
+/* Core DR 115: In contexts where deduction is done and fails, or in
+ contexts where deduction is not done, if a template argument list is
+ specified and it, along with any default template arguments, identifies
+ a single function template specialization, then the template-id is an
+ lvalue for the function template specialization. */
+
+tree
+resolve_nondeduced_context (tree orig_expr, tsubst_flags_t complain)
+{
+ tree expr, offset, baselink;
+ bool addr;
+
+ if (!type_unknown_p (orig_expr))
+ return orig_expr;
+
+ expr = orig_expr;
+ addr = false;
+ offset = NULL_TREE;
+ baselink = NULL_TREE;
+
+ if (TREE_CODE (expr) == ADDR_EXPR)
+ {
+ expr = TREE_OPERAND (expr, 0);
+ addr = true;
+ }
+
+ return orig_expr;
+}
} // namespace Rust
diff --git a/gcc/rust/backend/rust-tree.h b/gcc/rust/backend/rust-tree.h
index b93e936..9e8de7c 100644
--- a/gcc/rust/backend/rust-tree.h
+++ b/gcc/rust/backend/rust-tree.h
@@ -158,6 +158,89 @@
#define VAR_OR_FUNCTION_DECL_CHECK(NODE) \
TREE_CHECK2 (NODE, VAR_DECL, FUNCTION_DECL)
+// forked from gcc/cp/c-common.h c_tree_index
+
+/* Standard named or nameless data types of the C compiler. */
+
+enum c_tree_index
+{
+ CTI_CHAR8_TYPE,
+ CTI_CHAR16_TYPE,
+ CTI_CHAR32_TYPE,
+ CTI_WCHAR_TYPE,
+ CTI_UNDERLYING_WCHAR_TYPE,
+ CTI_WINT_TYPE,
+ CTI_SIGNED_SIZE_TYPE, /* For format checking only. */
+ CTI_UNSIGNED_PTRDIFF_TYPE, /* For format checking only. */
+ CTI_INTMAX_TYPE,
+ CTI_UINTMAX_TYPE,
+ CTI_WIDEST_INT_LIT_TYPE,
+ CTI_WIDEST_UINT_LIT_TYPE,
+
+ /* Types for <stdint.h>, that may not be defined on all
+ targets. */
+ CTI_SIG_ATOMIC_TYPE,
+ CTI_INT8_TYPE,
+ CTI_INT16_TYPE,
+ CTI_INT32_TYPE,
+ CTI_INT64_TYPE,
+ CTI_UINT8_TYPE,
+ CTI_UINT16_TYPE,
+ CTI_UINT32_TYPE,
+ CTI_UINT64_TYPE,
+ CTI_INT_LEAST8_TYPE,
+ CTI_INT_LEAST16_TYPE,
+ CTI_INT_LEAST32_TYPE,
+ CTI_INT_LEAST64_TYPE,
+ CTI_UINT_LEAST8_TYPE,
+ CTI_UINT_LEAST16_TYPE,
+ CTI_UINT_LEAST32_TYPE,
+ CTI_UINT_LEAST64_TYPE,
+ CTI_INT_FAST8_TYPE,
+ CTI_INT_FAST16_TYPE,
+ CTI_INT_FAST32_TYPE,
+ CTI_INT_FAST64_TYPE,
+ CTI_UINT_FAST8_TYPE,
+ CTI_UINT_FAST16_TYPE,
+ CTI_UINT_FAST32_TYPE,
+ CTI_UINT_FAST64_TYPE,
+ CTI_INTPTR_TYPE,
+ CTI_UINTPTR_TYPE,
+
+ CTI_CHAR_ARRAY_TYPE,
+ CTI_CHAR8_ARRAY_TYPE,
+ CTI_CHAR16_ARRAY_TYPE,
+ CTI_CHAR32_ARRAY_TYPE,
+ CTI_WCHAR_ARRAY_TYPE,
+ CTI_STRING_TYPE,
+ CTI_CONST_STRING_TYPE,
+
+ /* Type for boolean expressions (bool in C++, int in C). */
+ CTI_TRUTHVALUE_TYPE,
+ CTI_TRUTHVALUE_TRUE,
+ CTI_TRUTHVALUE_FALSE,
+
+ CTI_DEFAULT_FUNCTION_TYPE,
+
+ CTI_NULL,
+
+ /* These are not types, but we have to look them up all the time. */
+ CTI_FUNCTION_NAME_DECL,
+ CTI_PRETTY_FUNCTION_NAME_DECL,
+ CTI_C99_FUNCTION_NAME_DECL,
+
+ CTI_MODULE_HWM,
+ /* Below here entities change during compilation. */
+
+ CTI_SAVED_FUNCTION_NAME_DECLS,
+
+ CTI_MAX
+};
+
+// forked from gcc/c-family/c-common.h c_tree_index
+
+extern GTY (()) tree c_global_trees[CTI_MAX];
+
// forked from gcc/cp/cp-tree.h cp_tree_index
enum cp_tree_index
@@ -307,6 +390,71 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX];
/* std::align_val_t */
#define align_type_node cp_global_trees[CPTI_ALIGN_TYPE]
+#define char8_type_node c_global_trees[CTI_CHAR8_TYPE]
+#define char16_type_node c_global_trees[CTI_CHAR16_TYPE]
+#define char32_type_node c_global_trees[CTI_CHAR32_TYPE]
+#define wchar_type_node c_global_trees[CTI_WCHAR_TYPE]
+#define underlying_wchar_type_node c_global_trees[CTI_UNDERLYING_WCHAR_TYPE]
+#define wint_type_node c_global_trees[CTI_WINT_TYPE]
+#define signed_size_type_node c_global_trees[CTI_SIGNED_SIZE_TYPE]
+#define unsigned_ptrdiff_type_node c_global_trees[CTI_UNSIGNED_PTRDIFF_TYPE]
+#define intmax_type_node c_global_trees[CTI_INTMAX_TYPE]
+#define uintmax_type_node c_global_trees[CTI_UINTMAX_TYPE]
+#define widest_integer_literal_type_node c_global_trees[CTI_WIDEST_INT_LIT_TYPE]
+#define widest_unsigned_literal_type_node \
+ c_global_trees[CTI_WIDEST_UINT_LIT_TYPE]
+
+#define sig_atomic_type_node c_global_trees[CTI_SIG_ATOMIC_TYPE]
+#define int8_type_node c_global_trees[CTI_INT8_TYPE]
+#define int16_type_node c_global_trees[CTI_INT16_TYPE]
+#define int32_type_node c_global_trees[CTI_INT32_TYPE]
+#define int64_type_node c_global_trees[CTI_INT64_TYPE]
+#define uint8_type_node c_global_trees[CTI_UINT8_TYPE]
+#define c_uint16_type_node c_global_trees[CTI_UINT16_TYPE]
+#define c_uint32_type_node c_global_trees[CTI_UINT32_TYPE]
+#define c_uint64_type_node c_global_trees[CTI_UINT64_TYPE]
+#define int_least8_type_node c_global_trees[CTI_INT_LEAST8_TYPE]
+#define int_least16_type_node c_global_trees[CTI_INT_LEAST16_TYPE]
+#define int_least32_type_node c_global_trees[CTI_INT_LEAST32_TYPE]
+#define int_least64_type_node c_global_trees[CTI_INT_LEAST64_TYPE]
+#define uint_least8_type_node c_global_trees[CTI_UINT_LEAST8_TYPE]
+#define uint_least16_type_node c_global_trees[CTI_UINT_LEAST16_TYPE]
+#define uint_least32_type_node c_global_trees[CTI_UINT_LEAST32_TYPE]
+#define uint_least64_type_node c_global_trees[CTI_UINT_LEAST64_TYPE]
+#define int_fast8_type_node c_global_trees[CTI_INT_FAST8_TYPE]
+#define int_fast16_type_node c_global_trees[CTI_INT_FAST16_TYPE]
+#define int_fast32_type_node c_global_trees[CTI_INT_FAST32_TYPE]
+#define int_fast64_type_node c_global_trees[CTI_INT_FAST64_TYPE]
+#define uint_fast8_type_node c_global_trees[CTI_UINT_FAST8_TYPE]
+#define uint_fast16_type_node c_global_trees[CTI_UINT_FAST16_TYPE]
+#define uint_fast32_type_node c_global_trees[CTI_UINT_FAST32_TYPE]
+#define uint_fast64_type_node c_global_trees[CTI_UINT_FAST64_TYPE]
+#define intptr_type_node c_global_trees[CTI_INTPTR_TYPE]
+#define uintptr_type_node c_global_trees[CTI_UINTPTR_TYPE]
+
+#define truthvalue_type_node c_global_trees[CTI_TRUTHVALUE_TYPE]
+#define truthvalue_true_node c_global_trees[CTI_TRUTHVALUE_TRUE]
+#define truthvalue_false_node c_global_trees[CTI_TRUTHVALUE_FALSE]
+
+#define char_array_type_node c_global_trees[CTI_CHAR_ARRAY_TYPE]
+#define char8_array_type_node c_global_trees[CTI_CHAR8_ARRAY_TYPE]
+#define char16_array_type_node c_global_trees[CTI_CHAR16_ARRAY_TYPE]
+#define char32_array_type_node c_global_trees[CTI_CHAR32_ARRAY_TYPE]
+#define wchar_array_type_node c_global_trees[CTI_WCHAR_ARRAY_TYPE]
+#define string_type_node c_global_trees[CTI_STRING_TYPE]
+#define const_string_type_node c_global_trees[CTI_CONST_STRING_TYPE]
+
+#define default_function_type c_global_trees[CTI_DEFAULT_FUNCTION_TYPE]
+
+#define function_name_decl_node c_global_trees[CTI_FUNCTION_NAME_DECL]
+#define pretty_function_name_decl_node \
+ c_global_trees[CTI_PRETTY_FUNCTION_NAME_DECL]
+#define c99_function_name_decl_node c_global_trees[CTI_C99_FUNCTION_NAME_DECL]
+#define saved_function_name_decls c_global_trees[CTI_SAVED_FUNCTION_NAME_DECLS]
+
+/* The node for C++ `__null'. */
+#define null_node c_global_trees[CTI_NULL]
+
/* We cache these tree nodes so as to call get_identifier less frequently.
For identifiers for functions, including special member functions such
as ctors and assignment operators, the nodes can be used (among other
@@ -911,6 +1059,45 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX];
/* Nonzero if DECL was declared with '= default' (maybe implicitly). */
#define DECL_DEFAULTED_FN(DECL) (LANG_DECL_FN_CHECK (DECL)->defaulted_p)
+/* True if NODE is a brace-enclosed initializer. */
+#define BRACE_ENCLOSED_INITIALIZER_P(NODE) \
+ (TREE_CODE (NODE) == CONSTRUCTOR && TREE_TYPE (NODE) == init_list_type_node)
+
+/* True if FNDECL is an immediate function. */
+#define DECL_IMMEDIATE_FUNCTION_P(NODE) \
+ (DECL_LANG_SPECIFIC (FUNCTION_DECL_CHECK (NODE)) \
+ ? LANG_DECL_FN_CHECK (NODE)->immediate_fn_p \
+ : false)
+#define SET_DECL_IMMEDIATE_FUNCTION_P(NODE) \
+ (retrofit_lang_decl (FUNCTION_DECL_CHECK (NODE)), \
+ LANG_DECL_FN_CHECK (NODE)->immediate_fn_p = true)
+
+/* True if this CONSTRUCTOR should not be used as a variable initializer
+ because it was loaded from a constexpr variable with mutable fields. */
+#define CONSTRUCTOR_MUTABLE_POISON(NODE) \
+ (TREE_LANG_FLAG_2 (CONSTRUCTOR_CHECK (NODE)))
+
+/* For a pointer-to-member constant `X::Y' this is the _DECL for
+ `Y'. */
+#define PTRMEM_CST_MEMBER(NODE) \
+ (((ptrmem_cst_t) PTRMEM_CST_CHECK (NODE))->member)
+
+/* Indicates whether a COMPONENT_REF or a SCOPE_REF has been parenthesized, an
+ INDIRECT_REF comes from parenthesizing a _DECL, or a PAREN_EXPR identifies a
+ parenthesized initializer relevant for decltype(auto). Currently only set
+ some of the time in C++14 mode. */
+
+#define REF_PARENTHESIZED_P(NODE) \
+ TREE_LANG_FLAG_2 (TREE_CHECK5 ((NODE), COMPONENT_REF, INDIRECT_REF, \
+ SCOPE_REF, VIEW_CONVERT_EXPR, PAREN_EXPR))
+
+/* Returns true if NODE is a pointer-to-member. */
+#define TYPE_PTRMEM_P(NODE) \
+ (TYPE_PTRDATAMEM_P (NODE) || TYPE_PTRMEMFUNC_P (NODE))
+
+/* Returns true if NODE is a pointer or a pointer-to-member. */
+#define TYPE_PTR_OR_PTRMEM_P(NODE) (TYPE_PTR_P (NODE) || TYPE_PTRMEM_P (NODE))
+
#if defined ENABLE_TREE_CHECKING
#define LANG_DECL_MIN_CHECK(NODE) \
@@ -1035,6 +1222,68 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX];
// Above macros are copied from gcc/cp/name-lookup.cc
+// forked from gcc/cp/cp-tree.h warning_sentinel
+
+/* RAII sentinel to disable certain warnings during template substitution
+ and elsewhere. */
+
+class warning_sentinel
+{
+public:
+ int &flag;
+ int val;
+ warning_sentinel (int &flag, bool suppress = true) : flag (flag), val (flag)
+ {
+ if (suppress)
+ flag = 0;
+ }
+ ~warning_sentinel () { flag = val; }
+};
+
+// forked from gcc/cp/cp-tree.h uid_sensitive_constexpr_evaluation_checker
+
+/* Used to determine whether uid_sensitive_constexpr_evaluation_p was
+ called and returned true, indicating that we've restricted constexpr
+ evaluation in order to avoid UID generation. We use this to control
+ updates to the fold_cache and cv_cache. */
+
+struct uid_sensitive_constexpr_evaluation_checker
+{
+ const unsigned saved_counter;
+ uid_sensitive_constexpr_evaluation_checker ();
+ bool evaluation_restricted_p () const;
+};
+
+// forked from gcc/cp/cp-tree.h iloc_sentinel
+
+/* RAII sentinel to temporarily override input_location. This will not set
+ input_location to UNKNOWN_LOCATION or BUILTINS_LOCATION. */
+
+class iloc_sentinel
+{
+ location_t saved_loc;
+
+public:
+ iloc_sentinel (location_t loc) : saved_loc (input_location)
+ {
+ if (loc >= RESERVED_LOCATION_COUNT)
+ input_location = loc;
+ }
+ ~iloc_sentinel () { input_location = saved_loc; }
+};
+
+// forked from gcc/cp/cp-tree.h ptrmem_cst
+
+struct GTY (()) ptrmem_cst
+{
+ struct tree_common common;
+ tree member;
+ location_t locus;
+};
+typedef struct ptrmem_cst *ptrmem_cst_t;
+
+// forked from gcc/cp/cp-tree.h named_decl_hash
+
/* hash traits for declarations. Hashes potential overload sets via
DECL_NAME. */
@@ -1736,8 +1985,8 @@ mark_use (tree expr, bool rvalue_p, bool read_p, location_t loc,
// function with no library fallback (or any of its bits, such as in
// a conversion to bool).
extern tree
-mark_rvalue_use (tree e, location_t loc /* = UNKNOWN_LOCATION */,
- bool reject_builtin /* = true */);
+mark_rvalue_use (tree, location_t = UNKNOWN_LOCATION,
+ bool reject_builtin = true);
// Called whenever an expression is used in an lvalue context.
extern tree
@@ -1901,6 +2150,50 @@ extern bool reduced_constant_expression_p (tree);
extern tree cv_unqualified (tree);
+extern tree cp_get_callee (tree);
+extern tree cp_get_callee_fndecl_nofold (tree);
+
+extern bool is_nondependent_static_init_expression (tree);
+
+extern tree
+maybe_constant_init (tree, tree = NULL_TREE, bool = false);
+
+extern tree build_nop (tree, tree);
+
+extern bool scalarish_type_p (const_tree);
+
+extern tree is_bitfield_expr_with_lowered_type (const_tree);
+
+extern tree convert_bitfield_to_declared_type (tree);
+
+extern tree
+cp_fold_maybe_rvalue (tree, bool);
+
+extern tree maybe_undo_parenthesized_ref (tree);
+
+extern tree
+fold_offsetof (tree, tree = size_type_node, tree_code ctx = ERROR_MARK);
+
+extern tree cp_truthvalue_conversion (tree, tsubst_flags_t);
+
+extern tree
+fold_non_dependent_expr (tree, tsubst_flags_t = tf_warning_or_error,
+ bool = false, tree = NULL_TREE);
+
+extern int char_type_p (tree);
+
+extern bool instantiation_dependent_expression_p (tree);
+
+extern bool type_has_nontrivial_copy_init (const_tree);
+
+extern tree build_local_temp (tree);
+
+extern bool is_normal_capture_proxy (tree);
+
+extern bool reject_gcc_builtin (const_tree, location_t = UNKNOWN_LOCATION);
+
+extern tree resolve_nondeduced_context (tree, tsubst_flags_t);
+
// forked from gcc/cp/cp-tree.h
enum
@@ -2062,6 +2355,13 @@ vec_safe_push (releasing_vec &r, const tree &t CXX_MEM_STAT_INFO)
return vec_safe_push (*&r, t PASS_MEM_STAT);
}
+inline bool
+null_node_p (const_tree expr)
+{
+ STRIP_ANY_LOCATION_WRAPPER (expr);
+ return expr == null_node;
+}
+
} // namespace Rust
#endif // RUST_TREE