From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1643) id BF17E385AE4F; Mon, 29 Aug 2022 15:32:33 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org BF17E385AE4F DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1661787153; bh=j0wHRJ3smVmVFUD8fj+Qhax6K//qfSKUSJaWzPLu7Yk=; h=From:To:Subject:Date:From; b=LzfAF/DU1h54UFugjTbCW12yDM60+YgUFjdSY9XhLf7CtLoTTbVvL48RCh0udtMt6 j+yDmfHPdL4vqaAl8VYjEwl8+pXRsZjCvZLyk0DMOJhs/g8MNx4FPv+FpIi+esYQHs KW1db4WLcHEgGq8Ju9ZFPTtDh22kGDURYM5NNOHM= 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: f6f1984c3e483e7c00ef8822d310d98ea752d92a X-Git-Newrev: b9c08d705e6174bbbd0670b196d24e00b6f84d33 Message-Id: <20220829153233.BF17E385AE4F@sourceware.org> Date: Mon, 29 Aug 2022 15:32:33 +0000 (GMT) List-Id: https://gcc.gnu.org/g:b9c08d705e6174bbbd0670b196d24e00b6f84d33 commit b9c08d705e6174bbbd0670b196d24e00b6f84d33 Author: Faisal Abbas <90.abbasfaisal@gmail.com> Date: Thu Jul 7 11:31:32 2022 +0100 gccrs const folding port: continue porting potential_constant_expression_1() Following functions are ported in this changeset: - type_memfn_quals - find_parameter_pack_data - conv_type_hasher - make_conv_op_name - builtin_pack_fn_p - builtin_pack_call_p - has_extra_args_mechanism_p - find_parameter_packs_r - type_memfn_rqual - maybe_add_lang_type_raw - type_of_this_parm - class_of_this_parm Following structs, classes and enums are ported in this changeset: - cxx_binding - c_common_identifier - lang_identifier - cp_ref_qualifier - find_parameter_pack_data - conv_type_hasher Signed-off-by: Faisal Abbas <90.abbasfaisal@gmail.com> Diff: --- gcc/rust/backend/rust-tree.cc | 304 +++++++++++++++++++++++++++++++++++++++++- gcc/rust/backend/rust-tree.h | 149 +++++++++++++++++++-- 2 files changed, 439 insertions(+), 14 deletions(-) diff --git a/gcc/rust/backend/rust-tree.cc b/gcc/rust/backend/rust-tree.cc index 4b63499c828..4359c3de987 100644 --- a/gcc/rust/backend/rust-tree.cc +++ b/gcc/rust/backend/rust-tree.cc @@ -1117,9 +1117,6 @@ is_overloaded_fn (tree x) if (TREE_CODE (x) == COMPONENT_REF) x = TREE_OPERAND (x, 1); - if ((TREE_CODE (x) == OVERLOAD && !OVL_SINGLE_P (x))) - return 2; - return OVL_P (x); } @@ -1165,4 +1162,305 @@ lookup_add (tree fns, tree lookup) return lookup; } + +// forked from gcc/cp/typeck.cc type_memfn_quals + +/* Returns the function-cv-quals for TYPE, which must be a FUNCTION_TYPE or + METHOD_TYPE. */ + +int +type_memfn_quals (const_tree type) +{ + if (TREE_CODE (type) == FUNCTION_TYPE) + return TYPE_QUALS (type); + else if (TREE_CODE (type) == METHOD_TYPE) + return rs_type_quals (class_of_this_parm (type)); + else + gcc_unreachable (); +} + +// forked from gcc/cp/pt.cc find_parameter_pack_data + +/* Structure used to track the progress of find_parameter_packs_r. */ +struct find_parameter_pack_data +{ + /* TREE_LIST that will contain all of the parameter packs found by + the traversal. */ + tree *parameter_packs; + + /* Set of AST nodes that have been visited by the traversal. */ + hash_set *visited; + + /* True iff we're making a type pack expansion. */ + bool type_pack_expansion_p; + + /* True iff we found a subtree that has the extra args mechanism. */ + bool found_extra_args_tree_p = false; +}; + +// forked from gcc/cp/lex.cc conv_type_hasher + +/* Hasher for the conversion operator name hash table. */ +struct conv_type_hasher : ggc_ptr_hash +{ + /* Hash NODE, an identifier node in the table. TYPE_UID is + suitable, as we're not concerned about matching canonicalness + here. */ + static hashval_t hash (tree node) + { + return (hashval_t) TYPE_UID (TREE_TYPE (node)); + } + + /* Compare NODE, an identifier node in the table, against TYPE, an + incoming TYPE being looked up. */ + static bool equal (tree node, tree type) { return TREE_TYPE (node) == type; } +}; + +static GTY (()) hash_table *conv_type_names; + +// forked from gcc/cp/lex.cc make_conv_op_name + +/* Return an identifier for a conversion operator to TYPE. We can get + from the returned identifier to the type. We store TYPE, which is + not necessarily the canonical type, which allows us to report the + form the user used in error messages. All these identifiers are + not in the identifier hash table, and have the same string name. + These IDENTIFIERS are not in the identifier hash table, and all + have the same IDENTIFIER_STRING. */ + +tree +make_conv_op_name (tree type) +{ + if (type == error_mark_node) + return error_mark_node; + + if (conv_type_names == NULL) + conv_type_names = hash_table::create_ggc (31); + + tree *slot + = conv_type_names->find_slot_with_hash (type, (hashval_t) TYPE_UID (type), + INSERT); + tree identifier = *slot; + if (!identifier) + { + /* Create a raw IDENTIFIER outside of the identifier hash + table. */ + identifier = copy_node (conv_op_identifier); + + /* Just in case something managed to bind. */ + IDENTIFIER_BINDING (identifier) = NULL; + + /* Hang TYPE off the identifier so it can be found easily later + when performing conversions. */ + TREE_TYPE (identifier) = type; + + *slot = identifier; + } + + return identifier; +} + +// forked from gcc/cp/pt.cc builtin_pack_fn_p + +/* True iff FN is a function representing a built-in variadic parameter + pack. */ + +bool +builtin_pack_fn_p (tree fn) +{ + if (!fn || TREE_CODE (fn) != FUNCTION_DECL + || !DECL_IS_UNDECLARED_BUILTIN (fn)) + return false; + + if (id_equal (DECL_NAME (fn), "__integer_pack")) + return true; + + return false; +} + +// forked from gcc/cp/pt.cc builtin_pack_call_p + +/* True iff CALL is a call to a function representing a built-in variadic + parameter pack. */ + +static bool +builtin_pack_call_p (tree call) +{ + if (TREE_CODE (call) != CALL_EXPR) + return false; + return builtin_pack_fn_p (CALL_EXPR_FN (call)); +} + +// forked from gcc/cp/pt.cc has_extra_args_mechanism_p + +/* Return true if the tree T has the extra args mechanism for + avoiding partial instantiation. */ + +static bool +has_extra_args_mechanism_p (const_tree t) +{ + return false; +} + +// forked from gcc/cp/pt.cc find_parameter_packs_r + +/* Identifies all of the argument packs that occur in a template + argument and appends them to the TREE_LIST inside DATA, which is a + find_parameter_pack_data structure. This is a subroutine of + make_pack_expansion and uses_parameter_packs. */ +static tree +find_parameter_packs_r (tree *tp, int *walk_subtrees, void *data) +{ + tree t = *tp; + struct find_parameter_pack_data *ppd + = (struct find_parameter_pack_data *) data; + bool parameter_pack_p = false; + +#define WALK_SUBTREE(NODE) \ + rs_walk_tree (&(NODE), &find_parameter_packs_r, ppd, ppd->visited) + + /* Don't look through typedefs; we are interested in whether a + parameter pack is actually written in the expression/type we're + looking at, not the target type. */ + if (TYPE_P (t) && typedef_variant_p (t)) + { + *walk_subtrees = 0; + return NULL_TREE; + } + + /* Identify whether this is a parameter pack or not. */ + switch (TREE_CODE (t)) + { + case FIELD_DECL: + case PARM_DECL: + break; + + case VAR_DECL: + break; + + case CALL_EXPR: + if (builtin_pack_call_p (t)) + parameter_pack_p = true; + break; + + case BASES: + parameter_pack_p = true; + break; + default: + /* Not a parameter pack. */ + break; + } + + if (parameter_pack_p) + { + /* Add this parameter pack to the list. */ + *ppd->parameter_packs = tree_cons (NULL_TREE, t, *ppd->parameter_packs); + } + + if (TYPE_P (t)) + rs_walk_tree (&TYPE_CONTEXT (t), &find_parameter_packs_r, ppd, + ppd->visited); + + /* This switch statement will return immediately if we don't find a + parameter pack. ??? Should some of these be in cp_walk_subtrees? */ + switch (TREE_CODE (t)) + { + case DECL_EXPR: { + tree decl = DECL_EXPR_DECL (t); + if (is_typedef_decl (decl)) + /* Since we stop at typedefs above, we need to look through them at + the point of the DECL_EXPR. */ + rs_walk_tree (&DECL_ORIGINAL_TYPE (decl), &find_parameter_packs_r, + ppd, ppd->visited); + return NULL_TREE; + } + + case INTEGER_TYPE: + rs_walk_tree (&TYPE_MAX_VALUE (t), &find_parameter_packs_r, ppd, + ppd->visited); + *walk_subtrees = 0; + return NULL_TREE; + + case IDENTIFIER_NODE: + rs_walk_tree (&TREE_TYPE (t), &find_parameter_packs_r, ppd, ppd->visited); + *walk_subtrees = 0; + return NULL_TREE; + + case DECLTYPE_TYPE: { + /* When traversing a DECLTYPE_TYPE_EXPR, we need to set + type_pack_expansion_p to false so that any placeholders + within the expression don't get marked as parameter packs. */ + bool type_pack_expansion_p = ppd->type_pack_expansion_p; + ppd->type_pack_expansion_p = false; + rs_walk_tree (&DECLTYPE_TYPE_EXPR (t), &find_parameter_packs_r, ppd, + ppd->visited); + ppd->type_pack_expansion_p = type_pack_expansion_p; + *walk_subtrees = 0; + return NULL_TREE; + } + + case IF_STMT: + rs_walk_tree (&IF_COND (t), &find_parameter_packs_r, ppd, ppd->visited); + rs_walk_tree (&THEN_CLAUSE (t), &find_parameter_packs_r, ppd, + ppd->visited); + rs_walk_tree (&ELSE_CLAUSE (t), &find_parameter_packs_r, ppd, + ppd->visited); + /* Don't walk into IF_STMT_EXTRA_ARGS. */ + *walk_subtrees = 0; + return NULL_TREE; + + case FUNCTION_TYPE: + case METHOD_TYPE: + WALK_SUBTREE (TYPE_RAISES_EXCEPTIONS (t)); + break; + + default: + return NULL_TREE; + } + +#undef WALK_SUBTREE + + return NULL_TREE; +} + +// forked from gcc/cp/typeck.cc type_memfn_rqual + +/* Returns the function-ref-qualifier for TYPE */ + +rs_ref_qualifier +type_memfn_rqual (const_tree type) +{ + gcc_assert (FUNC_OR_METHOD_TYPE_P (type)); + + if (!FUNCTION_REF_QUALIFIED (type)) + return REF_QUAL_NONE; + else if (FUNCTION_RVALUE_QUALIFIED (type)) + return REF_QUAL_RVALUE; + else + return REF_QUAL_LVALUE; +} + +// forked from gcc/cp/lex.cc maybe_add_lang_type_raw + +/* Add a raw lang_type to T, a type, should it need one. */ + +bool +maybe_add_lang_type_raw (tree t) +{ + if (!RECORD_OR_UNION_CODE_P (TREE_CODE (t))) + return false; + + auto *lt = (struct lang_type *) (ggc_internal_cleared_alloc ( + sizeof (struct lang_type))); + TYPE_LANG_SPECIFIC (t) = lt; + + if (GATHER_STATISTICS) + { + tree_node_counts[(int) lang_type] += 1; + tree_node_sizes[(int) lang_type] += sizeof (struct lang_type); + } + + return true; +} + } // namespace Rust diff --git a/gcc/rust/backend/rust-tree.h b/gcc/rust/backend/rust-tree.h index 8d9b9f0d957..99ec33c640d 100644 --- a/gcc/rust/backend/rust-tree.h +++ b/gcc/rust/backend/rust-tree.h @@ -22,6 +22,7 @@ #include "rust-system.h" #include "coretypes.h" #include "tree.h" +#include "cpplib.h" /* Returns true if NODE is a pointer. */ #define TYPE_PTR_P(NODE) (TREE_CODE (NODE) == POINTER_TYPE) @@ -664,6 +665,74 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX]; order. */ #define MAYBE_CLASS_TYPE_P(T) (WILDCARD_TYPE_P (T) || CLASS_TYPE_P (T)) +/* 1 iff FUNCTION_TYPE or METHOD_TYPE has a ref-qualifier (either & or &&). */ +#define FUNCTION_REF_QUALIFIED(NODE) \ + TREE_LANG_FLAG_4 (FUNC_OR_METHOD_CHECK (NODE)) + +/* 1 iff FUNCTION_TYPE or METHOD_TYPE has &&-ref-qualifier. */ +#define FUNCTION_RVALUE_QUALIFIED(NODE) \ + TREE_LANG_FLAG_5 (FUNC_OR_METHOD_CHECK (NODE)) + +/* Get the POINTER_TYPE to the METHOD_TYPE associated with this + pointer to member function. TYPE_PTRMEMFUNC_P _must_ be true, + before using this macro. */ +#define TYPE_PTRMEMFUNC_FN_TYPE(NODE) \ + (cp_build_qualified_type (TREE_TYPE (TYPE_FIELDS (NODE)), \ + rs_type_quals (NODE))) + +/* As above, but can be used in places that want an lvalue at the expense + of not necessarily having the correct cv-qualifiers. */ +#define TYPE_PTRMEMFUNC_FN_TYPE_RAW(NODE) (TREE_TYPE (TYPE_FIELDS (NODE))) + +/* True if this type is dependent. This predicate is only valid if + TYPE_DEPENDENT_P_VALID is true. */ +#define TYPE_DEPENDENT_P(NODE) TYPE_LANG_FLAG_0 (NODE) + +/* True if dependent_type_p has been called for this type, with the + result that TYPE_DEPENDENT_P is valid. */ +#define TYPE_DEPENDENT_P_VALID(NODE) TYPE_LANG_FLAG_6 (NODE) + +/* Nonzero for _TYPE node means that this type does not have a trivial + destructor. Therefore, destroying an object of this type will + involve a call to a destructor. This can apply to objects of + ARRAY_TYPE if the type of the elements needs a destructor. */ +#define TYPE_HAS_NONTRIVIAL_DESTRUCTOR(NODE) (TYPE_LANG_FLAG_4 (NODE)) + +/* For FUNCTION_TYPE or METHOD_TYPE, a list of the exceptions that + this type can raise. Each TREE_VALUE is a _TYPE. The TREE_VALUE + will be NULL_TREE to indicate a throw specification of `()', or + no exceptions allowed. For a noexcept specification, TREE_VALUE + is NULL_TREE and TREE_PURPOSE is the constant-expression. For + a deferred noexcept-specification, TREE_PURPOSE is a DEFERRED_NOEXCEPT + (for templates) or an OVERLOAD list of functions (for implicitly + declared functions). */ +#define TYPE_RAISES_EXCEPTIONS(NODE) \ + TYPE_LANG_SLOT_1 (FUNC_OR_METHOD_CHECK (NODE)) + +/* Identifiers map directly to block or class-scope bindings. + Namespace-scope bindings are held in hash tables on the respective + namespaces. The identifier bindings are the innermost active + binding, from whence you can get the decl and/or implicit-typedef + of an elaborated type. When not bound to a local entity the + values are NULL. */ +#define IDENTIFIER_BINDING(NODE) (LANG_IDENTIFIER_CAST (NODE)->bindings) + +#define LANG_IDENTIFIER_CAST(NODE) \ + ((struct lang_identifier *) IDENTIFIER_NODE_CHECK (NODE)) + +/* IF_STMT accessors. These give access to the condition of the if + statement, the then block of the if statement, and the else block + of the if statement if it exists. */ +#define IF_COND(NODE) TREE_OPERAND (IF_STMT_CHECK (NODE), 0) +#define THEN_CLAUSE(NODE) TREE_OPERAND (IF_STMT_CHECK (NODE), 1) +#define ELSE_CLAUSE(NODE) TREE_OPERAND (IF_STMT_CHECK (NODE), 2) +#define IF_SCOPE(NODE) TREE_OPERAND (IF_STMT_CHECK (NODE), 3) +#define IF_STMT_CONSTEXPR_P(NODE) TREE_LANG_FLAG_0 (IF_STMT_CHECK (NODE)) +#define IF_STMT_CONSTEVAL_P(NODE) TREE_LANG_FLAG_2 (IF_STMT_CHECK (NODE)) + +/* The expression in question for a DECLTYPE_TYPE. */ +#define DECLTYPE_TYPE_EXPR(NODE) (TYPE_VALUES_RAW (DECLTYPE_TYPE_CHECK (NODE))) + // Below macros are copied from gcc/c-family/c-common.h /* In a FIELD_DECL, nonzero if the decl was originally a bitfield. */ @@ -689,17 +758,6 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX]; ((rs_type_quals (NODE) & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE)) \ == TYPE_QUAL_CONST) -/* [basic.fundamental] - - Types bool, char, wchar_t, and the signed and unsigned integer types - are collectively called integral types. - - Note that INTEGRAL_TYPE_P, as defined in tree.h, allows enumeration - types as well, which is incorrect in C++. Keep these checks in - ascending code order. */ -#define RS_INTEGRAL_TYPE_P(TYPE) \ - (TREE_CODE (TYPE) == BOOLEAN_TYPE || TREE_CODE (TYPE) == INTEGER_TYPE) - /* Returns true if TYPE is an integral or enumeration name. Keep these checks in ascending code order. */ #define INTEGRAL_OR_ENUMERATION_TYPE_P(TYPE) \ @@ -740,6 +798,44 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX]; // Above macros are copied from gcc/cp/name-lookup.cc +// forked from gcc/cp/name-lookup.h + +/* Datatype that represents binding established by a declaration between + a name and a C++ entity. */ +struct GTY (()) cxx_binding +{ + /* Link to chain together various bindings for this name. */ + cxx_binding *previous; + /* The non-type entity this name is bound to. */ + tree value; + /* The type entity this name is bound to. */ + tree type; + + bool value_is_inherited : 1; + bool is_local : 1; + bool type_is_hidden : 1; +}; + +// forked from gcc/c-family/c-common.h c_common_identifier + +/* Identifier part common to the C front ends. Inherits from + tree_identifier, despite appearances. */ +struct GTY (()) c_common_identifier +{ + struct tree_common common; + struct cpp_hashnode node; // from cpplib.h +}; + +// forked from gcc/cp/cp-tree.h lang_identifier + +/* Language-dependent contents of an identifier. */ + +struct GTY (()) lang_identifier +{ + struct c_common_identifier c_common; + cxx_binding *bindings; +}; + // forked from gcc/cp/cp-tree.h tree_overload /* OVL_HIDDEN_P nodes come before other nodes. */ @@ -953,6 +1049,15 @@ struct GTY (()) lang_type namespace Rust { +// forked from gcc/cp/cp-tree.h cp_ref_qualifier + +enum rs_ref_qualifier +{ + REF_QUAL_NONE = 0, + REF_QUAL_LVALUE = 1, + REF_QUAL_RVALUE = 2 +}; + // forked from gcc/cp/cp-tree.h tsubst_flags /* Bitmask flags to control type substitution. */ @@ -1227,6 +1332,28 @@ ovl_first (tree node) return node; } +// forked from gcc/cp/cp-tree.h type_of_this_parm + +/* Return the type of the `this' parameter of FNTYPE. */ + +inline tree +type_of_this_parm (const_tree fntype) +{ + function_args_iterator iter; + gcc_assert (TREE_CODE (fntype) == METHOD_TYPE); + function_args_iter_init (&iter, fntype); + return function_args_iter_cond (&iter); +} + +// forked from gcc/cp/cp-tree.h class_of_this_parm + +/* Return the class of the `this' parameter of FNTYPE. */ + +inline tree +class_of_this_parm (const_tree fntype) +{ + return TREE_TYPE (type_of_this_parm (fntype)); +} } // namespace Rust #endif // RUST_TREE