aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-06-29 13:39:05 +0000
committerGitHub <noreply@github.com>2022-06-29 13:39:05 +0000
commit9976c571ff14dc8e3da3ecd719f42b903a30f466 (patch)
tree96b3ba272723dfc1074c8f513abd2fddd0910999 /gcc
parentc88cc0aa644836c361ce5d8ff5225a9c12333dea (diff)
parent2a7a0589f62ab9157d9f862ec2fd7d680c53c5f3 (diff)
downloadgcc-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.cc40
-rw-r--r--gcc/rust/backend/rust-tree.cc111
-rw-r--r--gcc/rust/backend/rust-tree.h75
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