From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1643) id 270353856948; Mon, 29 Aug 2022 15:32:59 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 270353856948 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1661787179; bh=KeoT2urKpvHx/nMejzK4KRjtVEuijQS89mEr/OR0e48=; h=From:To:Subject:Date:From; b=gVJszJwKwnIW8CaVYaKPzj6Qx/wvP77S6sNrYa+Cn2LjRjoyea4rvPkTZ5IhhBFCT Jlm6lBmSIrRt+Bp+dunYYXEYp3MqA9enwqt2TADHTo4tRFcIbyGOT+16e5ulvYKEhZ i1yiBNhyZ3atcxC4jJiye1/6Zt/HY1rePLs56wos= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Thomas Schwinge To: gcc-cvs@gcc.gnu.org Subject: [gcc/devel/rust/master] gccrs const folding port: continue porting potential_constant_expression_1() X-Act-Checkin: gcc X-Git-Author: Faisal Abbas <90.abbasfaisal@gmail.com> X-Git-Refname: refs/heads/devel/rust/master X-Git-Oldrev: 7c13a2e5873f5919c00b5f37b6db52af8d0f7300 X-Git-Newrev: a00b61e6bfc4a79af55236db0e602e09cd8fda72 Message-Id: <20220829153259.270353856948@sourceware.org> Date: Mon, 29 Aug 2022 15:32:59 +0000 (GMT) List-Id: https://gcc.gnu.org/g:a00b61e6bfc4a79af55236db0e602e09cd8fda72 commit a00b61e6bfc4a79af55236db0e602e09cd8fda72 Author: Faisal Abbas <90.abbasfaisal@gmail.com> Date: Mon Jul 18 16:07:22 2022 +0100 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> Diff: --- gcc/rust/backend/rust-constexpr.cc | 105 +++++++- gcc/rust/backend/rust-tree.cc | 501 ++++++++++++++++++++++++++++++++++++- gcc/rust/backend/rust-tree.h | 304 +++++++++++++++++++++- 3 files changed, 899 insertions(+), 11 deletions(-) diff --git a/gcc/rust/backend/rust-constexpr.cc b/gcc/rust/backend/rust-constexpr.cc index 8fb378fbda5..189badabf94 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 *cleanups; + /* Heap VAR_DECLs created during the evaluation of the outermost constant + expression. */ + auto_vec 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 9221f7bb081..22e91f4d828 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 global_tree_arys[] = { std::pair (cp_global_trees, CPTI_MODULE_HWM), + std::pair (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 *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 % to static data member %qD", expr); + return error_mark_node; + + case CALL_EXPR: + case TARGET_EXPR: + error ("cannot apply % when % is overloaded"); + return error_mark_node; + + case NOP_EXPR: + case INDIRECT_REF: + if (!TREE_CONSTANT (TREE_OPERAND (expr, 0))) + { + error ("cannot apply % 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 b93e9364990..9e8de7cf833 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 , 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