diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2022-06-29 13:39:05 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-06-29 13:39:05 +0000 |
commit | 9976c571ff14dc8e3da3ecd719f42b903a30f466 (patch) | |
tree | 96b3ba272723dfc1074c8f513abd2fddd0910999 /gcc | |
parent | c88cc0aa644836c361ce5d8ff5225a9c12333dea (diff) | |
parent | 2a7a0589f62ab9157d9f862ec2fd7d680c53c5f3 (diff) | |
download | gcc-9976c571ff14dc8e3da3ecd719f42b903a30f466.zip gcc-9976c571ff14dc8e3da3ecd719f42b903a30f466.tar.gz gcc-9976c571ff14dc8e3da3ecd719f42b903a30f466.tar.bz2 |
Merge #1338
1338: gccrs const folding port: continue porting potential_constant_expression_1() r=philberty a=abbasfaisal
Card: [Link](https://github.com/Rust-GCC/gccrs/projects/16#card-82300805).
Target function: [Link](https://github.com/Rust-GCC/gccrs/blob/master/gcc/cp/constexpr.cc#L8350)
Following functions are ported in this changeset:
- [maybe_constexpr_fn](https://github.com/Rust-GCC/gccrs/blob/master/gcc/cp/constexpr.cc#L5495)
- [get_nth_callarg](https://github.com/Rust-GCC/gccrs/blob/master/gcc/cp/constexpr.cc#L1333)
- [var_in_maybe_constexpr_fn](https://github.com/Rust-GCC/gccrs/blob/master/gcc/cp/constexpr.cc#L5507)
- [array_type_nelts_top](https://github.com/Rust-GCC/gccrs/blob/master/gcc/cp/tree.cc#L3055)
- [builtin_valid_in_constant_expr_p](https://github.com/Rust-GCC/gccrs/blob/master/gcc/cp/tree.cc#L445)
- [decl_maybe_constant_var_p](https://github.com/Rust-GCC/gccrs/blob/master/gcc/cp/decl2.cc#L4623)
- [cp_type_quals](https://github.com/Rust-GCC/gccrs/blob/master/gcc/cp/typeck.cc#L10946)
Co-authored-by: Faisal Abbas <90.abbasfaisal@gmail.com>
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/backend/rust-constexpr.cc | 40 | ||||
-rw-r--r-- | gcc/rust/backend/rust-tree.cc | 111 | ||||
-rw-r--r-- | gcc/rust/backend/rust-tree.h | 75 |
3 files changed, 219 insertions, 7 deletions
diff --git a/gcc/rust/backend/rust-constexpr.cc b/gcc/rust/backend/rust-constexpr.cc index f77fb3a..53c6ef6 100644 --- a/gcc/rust/backend/rust-constexpr.cc +++ b/gcc/rust/backend/rust-constexpr.cc @@ -397,5 +397,45 @@ get_function_named_in_call (tree t) return fun; } +// forked from gcc/cp/constexpr.cc maybe_constexpr_fn + +/* True if a function might be declared constexpr */ + +bool +maybe_constexpr_fn (tree t) +{ + return (DECL_DECLARED_CONSTEXPR_P (t)); +} + +// forked from gcc/cp/constexpr.cc get_nth_callarg + +/* We have an expression tree T that represents a call, either CALL_EXPR. + Return the Nth argument. */ + +inline tree +get_nth_callarg (tree t, int n) +{ + switch (TREE_CODE (t)) + { + case CALL_EXPR: + return CALL_EXPR_ARG (t, n); + + default: + gcc_unreachable (); + return NULL; + } +} + +// forked from gcc/cp/constexpr.cc var_in_maybe_constexpr_fn + +/* True if T was declared in a function that might be constexpr: either a + function that was declared constexpr. */ + +bool +var_in_maybe_constexpr_fn (tree t) +{ + return (DECL_FUNCTION_SCOPE_P (t) && maybe_constexpr_fn (DECL_CONTEXT (t))); +} + } // namespace Compile } // namespace Rust diff --git a/gcc/rust/backend/rust-tree.cc b/gcc/rust/backend/rust-tree.cc index a71b584..3d71e19 100644 --- a/gcc/rust/backend/rust-tree.cc +++ b/gcc/rust/backend/rust-tree.cc @@ -766,7 +766,7 @@ out: locations. */ location_t -cp_expr_location (const_tree t_) +rs_expr_location (const_tree t_) { tree t = CONST_CAST_TREE (t_); if (t == NULL_TREE) @@ -775,7 +775,7 @@ cp_expr_location (const_tree t_) return EXPR_LOCATION (t); } -// forked from gcc/cp/class.cc +// forked from gcc/cp/class.cc is_really_empty_class /* Returns true if TYPE contains no actual data, just various possible combinations of empty classes. If IGNORE_VPTR is true, @@ -848,4 +848,111 @@ array_type_nelts_top (tree type) array_type_nelts (type), size_one_node); } +// forked from gcc/cp/tree.cc builtin_valid_in_constant_expr_p + +/* Test whether DECL is a builtin that may appear in a + constant-expression. */ + +bool +builtin_valid_in_constant_expr_p (const_tree decl) +{ + STRIP_ANY_LOCATION_WRAPPER (decl); + if (TREE_CODE (decl) != FUNCTION_DECL) + /* Not a function. */ + return false; + if (DECL_BUILT_IN_CLASS (decl) != BUILT_IN_NORMAL) + { + if (fndecl_built_in_p (decl, BUILT_IN_FRONTEND)) + switch (DECL_FE_FUNCTION_CODE (decl)) + { + case RS_BUILT_IN_IS_CONSTANT_EVALUATED: + case RS_BUILT_IN_SOURCE_LOCATION: + case RS_BUILT_IN_IS_CORRESPONDING_MEMBER: + case RS_BUILT_IN_IS_POINTER_INTERCONVERTIBLE_WITH_CLASS: + return true; + default: + break; + } + /* Not a built-in. */ + return false; + } + switch (DECL_FUNCTION_CODE (decl)) + { + /* These always have constant results like the corresponding + macros/symbol. */ + case BUILT_IN_FILE: + case BUILT_IN_FUNCTION: + case BUILT_IN_LINE: + + /* The following built-ins are valid in constant expressions + when their arguments are. */ + case BUILT_IN_ADD_OVERFLOW_P: + case BUILT_IN_SUB_OVERFLOW_P: + case BUILT_IN_MUL_OVERFLOW_P: + + /* These have constant results even if their operands are + non-constant. */ + case BUILT_IN_CONSTANT_P: + case BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE: + return true; + default: + return false; + } +} + +// forked from gcc/cp/decl2.cc decl_maybe_constant_var_p + +/* Returns true if DECL could be a symbolic constant variable, depending on + its initializer. */ + +bool +decl_maybe_constant_var_p (tree decl) +{ + tree type = TREE_TYPE (decl); + if (!VAR_P (decl)) + return false; + if (DECL_DECLARED_CONSTEXPR_P (decl)) + return true; + if (DECL_HAS_VALUE_EXPR_P (decl)) + /* A proxy isn't constant. */ + return false; + if (TYPE_REF_P (type)) + /* References can be constant. */; + else if (RS_TYPE_CONST_NON_VOLATILE_P (type) + && INTEGRAL_OR_ENUMERATION_TYPE_P (type)) + /* And const integers. */; + else + return false; + + if (DECL_INITIAL (decl) && !DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)) + /* We know the initializer, and it isn't constant. */ + return false; + else + return true; +} + +// forked from gcc/cp/typeck.cc cp_type_quals + +/* Returns the type qualifiers for this type, including the qualifiers on the + elements for an array type. */ + +int +rs_type_quals (const_tree type) +{ + int quals; + /* This CONST_CAST is okay because strip_array_types returns its + argument unmodified and we assign it to a const_tree. */ + type = strip_array_types (CONST_CAST_TREE (type)); + if (type == error_mark_node + /* Quals on a FUNCTION_TYPE are memfn quals. */ + || TREE_CODE (type) == FUNCTION_TYPE) + return TYPE_UNQUALIFIED; + quals = TYPE_QUALS (type); + /* METHOD and REFERENCE_TYPEs should never have quals. */ + gcc_assert ( + (TREE_CODE (type) != METHOD_TYPE && !TYPE_REF_P (type)) + || ((quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE)) == TYPE_UNQUALIFIED)); + return quals; +} + } // namespace Rust diff --git a/gcc/rust/backend/rust-tree.h b/gcc/rust/backend/rust-tree.h index b564090..a667cbf 100644 --- a/gcc/rust/backend/rust-tree.h +++ b/gcc/rust/backend/rust-tree.h @@ -149,6 +149,13 @@ /* Nonzero if this class is "empty" in the sense of the C++ ABI. */ #define CLASSTYPE_EMPTY_P(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->empty_p) +/* True if DECL is declared 'constexpr'. */ +#define DECL_DECLARED_CONSTEXPR_P(DECL) \ + DECL_LANG_FLAG_8 (VAR_OR_FUNCTION_DECL_CHECK (DECL)) + +#define VAR_OR_FUNCTION_DECL_CHECK(NODE) \ + TREE_CHECK2 (NODE, VAR_DECL, FUNCTION_DECL) + // Below macros are copied from gcc/c-family/c-common.h /* In a FIELD_DECL, nonzero if the decl was originally a bitfield. */ @@ -162,6 +169,39 @@ #define DECL_UNNAMED_BIT_FIELD(NODE) \ (DECL_C_BIT_FIELD (NODE) && !DECL_NAME (NODE)) +/* 1 iff NODE is function-local. */ +#define DECL_FUNCTION_SCOPE_P(NODE) \ + (DECL_CONTEXT (NODE) && TREE_CODE (DECL_CONTEXT (NODE)) == FUNCTION_DECL) + +/* Nonzero if this type is const-qualified, but not + volatile-qualified. Other qualifiers are ignored. This macro is + used to test whether or not it is OK to bind an rvalue to a + reference. */ +#define RS_TYPE_CONST_NON_VOLATILE_P(NODE) \ + ((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) \ + (TREE_CODE (TYPE) == ENUMERAL_TYPE || RS_INTEGRAL_TYPE_P (TYPE)) + +/* Nonzero for a VAR_DECL that was initialized with a + constant-expression. */ +#define DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P(NODE) \ + (TREE_LANG_FLAG_2 (VAR_DECL_CHECK (NODE))) + // Above macros are copied from gcc/c-family/c-common.h // forked from gcc/cp/cp-tree.h treee_pair_s @@ -324,6 +364,17 @@ enum impl_conv_void ICV_THIRD_IN_FOR /* for increment expression */ }; +/* BUILT_IN_FRONTEND function codes. */ +enum rs_built_in_function +{ + RS_BUILT_IN_IS_CONSTANT_EVALUATED, + RS_BUILT_IN_INTEGER_PACK, + RS_BUILT_IN_IS_CORRESPONDING_MEMBER, + RS_BUILT_IN_IS_POINTER_INTERCONVERTIBLE_WITH_CLASS, + RS_BUILT_IN_SOURCE_LOCATION, + RS_BUILT_IN_LAST +}; + extern tree convert_to_void (tree expr, impl_conv_void implicit); @@ -405,13 +456,27 @@ pointer_offset_expression (tree base_tree, tree index_tree, location_t locus); but not all node kinds do (e.g. constants, and references to params, locals, etc), so we stash a copy here. */ -extern location_t cp_expr_location (const_tree); +extern location_t rs_expr_location (const_tree); extern int is_empty_class (tree type); extern tree array_type_nelts_top (tree); +extern bool +is_really_empty_class (tree, bool); + +extern bool builtin_valid_in_constant_expr_p (const_tree); + +extern bool maybe_constexpr_fn (tree); + +extern bool var_in_maybe_constexpr_fn (tree); + +extern int +rs_type_quals (const_tree type); + +extern bool decl_maybe_constant_var_p (tree); + extern tree rs_walk_subtrees (tree *, int *, walk_tree_fn, void *, hash_set<tree> *); #define rs_walk_tree(tp, func, data, pset) \ @@ -422,9 +487,9 @@ rs_walk_subtrees (tree *, int *, walk_tree_fn, void *, hash_set<tree> *); // forked from gcc/cp/cp-tree.h cp_expr_loc_or_loc inline location_t -cp_expr_loc_or_loc (const_tree t, location_t or_loc) +rs_expr_loc_or_loc (const_tree t, location_t or_loc) { - location_t loc = cp_expr_location (t); + location_t loc = rs_expr_location (t); if (loc == UNKNOWN_LOCATION) loc = or_loc; return loc; @@ -433,9 +498,9 @@ cp_expr_loc_or_loc (const_tree t, location_t or_loc) // forked from gcc/cp/cp-tree.h cp_expr_loc_or_input_loc inline location_t -cp_expr_loc_or_input_loc (const_tree t) +rs_expr_loc_or_input_loc (const_tree t) { - return cp_expr_loc_or_loc (t, input_location); + return rs_expr_loc_or_loc (t, input_location); } } // namespace Rust |