public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/rust/master] rust constexpr: port over cxx_eval_builtin_function_call().
@ 2022-08-29 15:35 Thomas Schwinge
  0 siblings, 0 replies; only message in thread
From: Thomas Schwinge @ 2022-08-29 15:35 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:533effe0f3f49c144df3e1a918f422d2982d21bf

commit 533effe0f3f49c144df3e1a918f422d2982d21bf
Author: Faisal Abbas <90.abbasfaisal@gmail.com>
Date:   Fri Aug 12 18:58:04 2022 +0100

    rust constexpr: port over cxx_eval_builtin_function_call().
    
    It still needs potential_constant_expression_1() which will be continued
    to be ported over.
    
    Signed-off-by: Faisal Abbas <90.abbasfaisal@gmail.com>

Diff:
---
 gcc/rust/backend/rust-constexpr.cc | 318 +++++++++++++++++++++++++++++++++++++
 gcc/rust/backend/rust-tree.cc      |  96 +++++++++++
 gcc/rust/backend/rust-tree.h       | 105 ++++++++++++
 3 files changed, 519 insertions(+)

diff --git a/gcc/rust/backend/rust-constexpr.cc b/gcc/rust/backend/rust-constexpr.cc
index e41d184cf71..190abc96070 100644
--- a/gcc/rust/backend/rust-constexpr.cc
+++ b/gcc/rust/backend/rust-constexpr.cc
@@ -1084,6 +1084,7 @@ init_subob_ctx (const constexpr_ctx *ctx, constexpr_ctx &new_ctx, tree index,
 	/* There's no well-defined subobject for this index.  */
 	new_ctx.object = NULL_TREE;
       else
+	// Faisal: commenting this out as not sure if it's needed and it's huge
 	// new_ctx.object = build_ctor_subob_ref (index, type, ctx->object);
 	;
     }
@@ -2761,6 +2762,217 @@ rs_bind_parameters_in_call (const constexpr_ctx *ctx, tree t, tree fun,
   return binds;
 }
 
+// forked from gcc/cp/constexpr.cc cxx_eval_builtin_function_call
+
+/* Attempt to evaluate T which represents a call to a builtin function.
+   We assume here that all builtin functions evaluate to scalar types
+   represented by _CST nodes.  */
+
+static tree
+eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,
+			    bool lval, bool *non_constant_p, bool *overflow_p)
+{
+  const int nargs = call_expr_nargs (t);
+  tree *args = (tree *) alloca (nargs * sizeof (tree));
+  tree new_call;
+  int i;
+
+  /* Don't fold __builtin_constant_p within a constexpr function.  */
+  bool bi_const_p = DECL_IS_BUILTIN_CONSTANT_P (fun);
+
+  /* If we aren't requiring a constant expression, defer __builtin_constant_p
+     in a constexpr function until we have values for the parameters.  */
+  if (bi_const_p && !ctx->manifestly_const_eval && current_function_decl
+      && DECL_DECLARED_CONSTEXPR_P (current_function_decl))
+    {
+      *non_constant_p = true;
+      return t;
+    }
+
+  /* For __builtin_is_constant_evaluated, defer it if not
+     ctx->manifestly_const_eval (as sometimes we try to constant evaluate
+     without manifestly_const_eval even expressions or parts thereof which
+     will later be manifestly const_eval evaluated), otherwise fold it to
+     true.  */
+  if (fndecl_built_in_p (fun, CP_BUILT_IN_IS_CONSTANT_EVALUATED,
+			 BUILT_IN_FRONTEND))
+    {
+      if (!ctx->manifestly_const_eval)
+	{
+	  *non_constant_p = true;
+	  return t;
+	}
+      return boolean_true_node;
+    }
+
+  if (fndecl_built_in_p (fun, CP_BUILT_IN_SOURCE_LOCATION, BUILT_IN_FRONTEND))
+    {
+      temp_override<tree> ovr (current_function_decl);
+      if (ctx->call && ctx->call->fundef)
+	current_function_decl = ctx->call->fundef->decl;
+      return fold_builtin_source_location (EXPR_LOCATION (t));
+    }
+
+  int strops = 0;
+  int strret = 0;
+  if (fndecl_built_in_p (fun, BUILT_IN_NORMAL))
+    switch (DECL_FUNCTION_CODE (fun))
+      {
+      case BUILT_IN_STRLEN:
+      case BUILT_IN_STRNLEN:
+	strops = 1;
+	break;
+      case BUILT_IN_MEMCHR:
+      case BUILT_IN_STRCHR:
+      case BUILT_IN_STRRCHR:
+	strops = 1;
+	strret = 1;
+	break;
+      case BUILT_IN_MEMCMP:
+      case BUILT_IN_STRCMP:
+	strops = 2;
+	break;
+      case BUILT_IN_STRSTR:
+	strops = 2;
+	strret = 1;
+	break;
+      case BUILT_IN_ASAN_POINTER_COMPARE:
+      case BUILT_IN_ASAN_POINTER_SUBTRACT:
+	/* These builtins shall be ignored during constant expression
+	   evaluation.  */
+	return void_node;
+      default:
+	break;
+      }
+
+  /* Be permissive for arguments to built-ins; __builtin_constant_p should
+     return constant false for a non-constant argument.  */
+  constexpr_ctx new_ctx = *ctx;
+  new_ctx.quiet = true;
+  for (i = 0; i < nargs; ++i)
+    {
+      tree arg = CALL_EXPR_ARG (t, i);
+      tree oarg = arg;
+
+      /* To handle string built-ins we need to pass ADDR_EXPR<STRING_CST> since
+	 expand_builtin doesn't know how to look in the values table.  */
+      bool strop = i < strops;
+      if (strop)
+	{
+	  STRIP_NOPS (arg);
+	  if (TREE_CODE (arg) == ADDR_EXPR)
+	    arg = TREE_OPERAND (arg, 0);
+	  else
+	    strop = false;
+	}
+
+      /* If builtin_valid_in_constant_expr_p is true,
+	 potential_constant_expression_1 has not recursed into the arguments
+	 of the builtin, verify it here.  */
+      if (!builtin_valid_in_constant_expr_p (fun)
+	  || potential_constant_expression (arg))
+	{
+	  bool dummy1 = false, dummy2 = false;
+	  arg
+	    = eval_constant_expression (&new_ctx, arg, false, &dummy1, &dummy2);
+	}
+
+      if (bi_const_p)
+	/* For __builtin_constant_p, fold all expressions with constant values
+	   even if they aren't C++ constant-expressions.  */
+	arg = cp_fold_rvalue (arg);
+      else if (strop)
+	{
+	  if (TREE_CODE (arg) == CONSTRUCTOR)
+	    arg = braced_lists_to_strings (TREE_TYPE (arg), arg);
+	  if (TREE_CODE (arg) == STRING_CST)
+	    arg = build_address (arg);
+	  else
+	    arg = oarg;
+	}
+
+      args[i] = arg;
+    }
+
+  bool save_ffbcp = force_folding_builtin_constant_p;
+  force_folding_builtin_constant_p |= ctx->manifestly_const_eval;
+  tree save_cur_fn = current_function_decl;
+  /* Return name of ctx->call->fundef->decl for __builtin_FUNCTION ().  */
+  if (fndecl_built_in_p (fun, BUILT_IN_FUNCTION) && ctx->call
+      && ctx->call->fundef)
+    current_function_decl = ctx->call->fundef->decl;
+  if (fndecl_built_in_p (fun,
+			 CP_BUILT_IN_IS_POINTER_INTERCONVERTIBLE_WITH_CLASS,
+			 BUILT_IN_FRONTEND))
+    {
+      location_t loc = EXPR_LOCATION (t);
+      if (nargs >= 1)
+	VERIFY_CONSTANT (args[0]);
+      new_call
+	= fold_builtin_is_pointer_inverconvertible_with_class (loc, nargs,
+							       args);
+    }
+  else if (fndecl_built_in_p (fun, CP_BUILT_IN_IS_CORRESPONDING_MEMBER,
+			      BUILT_IN_FRONTEND))
+    {
+      location_t loc = EXPR_LOCATION (t);
+      if (nargs >= 2)
+	{
+	  VERIFY_CONSTANT (args[0]);
+	  VERIFY_CONSTANT (args[1]);
+	}
+      new_call = fold_builtin_is_corresponding_member (loc, nargs, args);
+    }
+  else
+    new_call = fold_builtin_call_array (EXPR_LOCATION (t), TREE_TYPE (t),
+					CALL_EXPR_FN (t), nargs, args);
+  current_function_decl = save_cur_fn;
+  force_folding_builtin_constant_p = save_ffbcp;
+  if (new_call == NULL)
+    {
+      if (!*non_constant_p && !ctx->quiet)
+	{
+	  /* Do not allow__builtin_unreachable in constexpr function.
+	     The __builtin_unreachable call with BUILTINS_LOCATION
+	     comes from cp_maybe_instrument_return.  */
+	  if (fndecl_built_in_p (fun, BUILT_IN_UNREACHABLE)
+	      && EXPR_LOCATION (t) == BUILTINS_LOCATION)
+	    error ("%<constexpr%> call flows off the end of the function");
+	  else
+	    {
+	      new_call = build_call_array_loc (EXPR_LOCATION (t), TREE_TYPE (t),
+					       CALL_EXPR_FN (t), nargs, args);
+	      error ("%q+E is not a constant expression", new_call);
+	    }
+	}
+      *non_constant_p = true;
+      return t;
+    }
+
+  if (!potential_constant_expression (new_call))
+    {
+      if (!*non_constant_p && !ctx->quiet)
+	error ("%q+E is not a constant expression", new_call);
+      *non_constant_p = true;
+      return t;
+    }
+
+  if (strret)
+    {
+      /* memchr returns a pointer into the first argument, but we replaced the
+	 argument above with a STRING_CST; put it back it now.  */
+      tree op = CALL_EXPR_ARG (t, strret - 1);
+      STRIP_NOPS (new_call);
+      if (TREE_CODE (new_call) == POINTER_PLUS_EXPR)
+	TREE_OPERAND (new_call, 0) = op;
+      else if (TREE_CODE (new_call) == ADDR_EXPR)
+	new_call = op;
+    }
+
+  return eval_constant_expression (&new_ctx, new_call, lval, non_constant_p,
+				   overflow_p);
+}
+
 // Subroutine of cxx_eval_constant_expression.
 // Evaluate the call expression tree T in the context of OLD_CALL expression
 // evaluation.
@@ -2792,6 +3004,10 @@ eval_call_expression (const constexpr_ctx *ctx, tree t, bool lval,
       return t;
     }
 
+  if (fndecl_built_in_p (fun))
+    return eval_builtin_function_call (ctx, t, fun, lval, non_constant_p,
+				       overflow_p);
+
   bool non_constant_args = false;
   new_call.bindings
     = rs_bind_parameters_in_call (ctx, t, fun, non_constant_p, overflow_p,
@@ -4443,6 +4659,20 @@ is_static_init_expression (tree t)
   // faisal: just return false for now to make it compile
 }
 
+/* Like potential_constant_expression, but don't consider possible constexpr
+   substitution of the current function.  That is, PARM_DECL qualifies under
+   potential_constant_expression, but not here.
+
+   This is basically what you can check when any actual constant values might
+   be value-dependent.  */
+
+bool
+is_constant_expression (tree t)
+{
+  // return potential_constant_expression_1 (t, false, true, true, tf_none);
+  // faisal: just return false for now to make it compile
+}
+
 /* Returns true if T is a potential static initializer expression that is not
    instantiation-dependent.  */
 
@@ -4497,6 +4727,94 @@ maybe_constant_init (tree t, tree decl, bool manifestly_const_eval)
   return maybe_constant_init_1 (t, decl, true, manifestly_const_eval);
 }
 
+/* Returns true if T is a potential constant expression that is not
+   instantiation-dependent, and therefore a candidate for constant folding even
+   in a template.  */
+
+bool
+is_nondependent_constant_expression (tree t)
+{
+  return (!type_unknown_p (t) && is_constant_expression (t)
+	  && !instantiation_dependent_expression_p (t));
+}
+
+// forked from gcc/cp/parser.cc cp_unevaluated_operand
+
+/* Nonzero if we are parsing an unevaluated operand: an operand to
+   sizeof, typeof, or alignof.  */
+int cp_unevaluated_operand;
+
+// forked from gcc/cp/constexpr.cc cv_cache
+
+/* If T is a constant expression, returns its reduced value.
+   Otherwise, if T does not have TREE_CONSTANT set, returns T.
+   Otherwise, returns a version of T without TREE_CONSTANT.
+   MANIFESTLY_CONST_EVAL is true if T is manifestly const-evaluated
+   as per P0595.  */
+
+static GTY ((deletable)) hash_map<tree, tree> *cv_cache;
+
+// forked from gcc/cp/constexpr.cc maybe_constant_value
+
+tree
+maybe_constant_value (tree t, tree decl, bool manifestly_const_eval)
+{
+  tree r;
+
+  if (!is_nondependent_constant_expression (t))
+    {
+      if (TREE_OVERFLOW_P (t))
+	{
+	  t = build_nop (TREE_TYPE (t), t);
+	  TREE_CONSTANT (t) = false;
+	}
+      return t;
+    }
+  else if (CONSTANT_CLASS_P (t))
+    /* No caching or evaluation needed.  */
+    return t;
+
+  if (manifestly_const_eval)
+    return cxx_eval_outermost_constant_expr (t, true, true, true, false, decl);
+
+  if (cv_cache == NULL)
+    cv_cache = hash_map<tree, tree>::create_ggc (101);
+  if (tree *cached = cv_cache->get (t))
+    {
+      r = *cached;
+      if (r != t)
+	{
+	  // Faisal: commenting this out as not sure if it's needed and it's
+	  // huge r = break_out_target_exprs (r, /*clear_loc*/true);
+	  protected_set_expr_location (r, EXPR_LOCATION (t));
+	}
+      return r;
+    }
+
+  /* Don't evaluate an unevaluated operand.  */
+  if (cp_unevaluated_operand)
+    return t;
+
+  uid_sensitive_constexpr_evaluation_checker c;
+  r = cxx_eval_outermost_constant_expr (t, true, true, false, false, decl);
+  gcc_checking_assert (
+    r == t || CONVERT_EXPR_P (t) || TREE_CODE (t) == VIEW_CONVERT_EXPR
+    || (TREE_CONSTANT (t) && !TREE_CONSTANT (r)) || !rs_tree_equal (r, t));
+  if (!c.evaluation_restricted_p ())
+    cv_cache->put (t, r);
+  return r;
+}
+
+// forked from gcc/cp/constexpr.cc
+
+bool
+potential_constant_expression (tree t)
+{
+  // return potential_constant_expression_1 (t, false, true, false, tf_none);
+  // Faisal: return false until we port above call to make the code compile
+  return false;
+}
+
 // #include "gt-rust-rust-constexpr.h"
 
 } // namespace Compile
diff --git a/gcc/rust/backend/rust-tree.cc b/gcc/rust/backend/rust-tree.cc
index e1e56fc8336..beb4711493d 100644
--- a/gcc/rust/backend/rust-tree.cc
+++ b/gcc/rust/backend/rust-tree.cc
@@ -5257,6 +5257,8 @@ fold_builtin_is_pointer_inverconvertible_with_class (location_t loc, int nargs,
 		      build_zero_cst (TREE_TYPE (arg)));
 }
 
+// forked from gcc/c-family/c-common.cc registered_builtin_types
+
 /* Used for communication between c_common_type_for_mode and
    c_register_builtin_type.  */
 tree registered_builtin_types;
@@ -5267,6 +5269,8 @@ tree registered_builtin_types;
    If the mode is a fixed-point mode,
    then UNSIGNEDP selects between saturating and nonsaturating types.  */
 
+// forked from gcc/c-family/c-common.cc c_common_type_for_mode
+
 tree
 c_common_type_for_mode (machine_mode mode, int unsignedp)
 {
@@ -5487,6 +5491,8 @@ c_common_type_for_mode (machine_mode mode, int unsignedp)
   return NULL_TREE;
 }
 
+// forked from gcc/cp/semantics.cc finish_underlying_type
+
 /* Implement the __underlying_type keyword: Return the underlying
    type of TYPE, suitable for use as a type-specifier.  */
 
@@ -5516,6 +5522,8 @@ finish_underlying_type (tree type)
   return underlying_type;
 }
 
+// forked from gcc/cp/typeck.cc layout_compatible_type_p
+
 /* Return true if TYPE1 and TYPE2 are layout-compatible types.  */
 
 bool
@@ -5619,6 +5627,8 @@ layout_compatible_type_p (tree type1, tree type2)
   return same_type_p (type1, type2);
 }
 
+// forked from gcc/cp/semnatics.cc is_corresponding_member_union
+
 /* Helper function for is_corresponding_member_aggr.  Return true if
    MEMBERTYPE pointer-to-data-member ARG can be found in anonymous
    union or structure BASETYPE.  */
@@ -5648,6 +5658,8 @@ is_corresponding_member_union (tree basetype, tree membertype, tree arg)
   return false;
 }
 
+// forked from gcc/cp/typeck.cc next_common_initial_seqence
+
 /* Helper function for layout_compatible_type_p and
    is_corresponding_member_aggr.  Advance to next members (NULL if
    no further ones) and return true if those members are still part of
@@ -5713,6 +5725,8 @@ next_common_initial_seqence (tree &memb1, tree &memb2)
   return true;
 }
 
+// forked from gcc/cp/semantics.cc is_corresponding_member_aggr
+
 /* Helper function for fold_builtin_is_corresponding_member call.
    Return boolean_false_node if MEMBERTYPE1 BASETYPE1::*ARG1 and
    MEMBERTYPE2 BASETYPE2::*ARG2 aren't corresponding members,
@@ -5833,6 +5847,8 @@ is_corresponding_member_aggr (location_t loc, tree basetype1, tree membertype1,
   return ret;
 }
 
+// forked from gcc/cp/call.cc null_member_pointer_value_p
+
 /* Returns true iff T is a null member pointer value (4.11).  */
 
 bool
@@ -5850,6 +5866,8 @@ null_member_pointer_value_p (tree t)
     return false;
 }
 
+// forked from gcc/cp/semantics.cc fold_builtin_is_corresponding_member
+
 /* Fold __builtin_is_corresponding_member call.  */
 
 tree
@@ -5937,4 +5955,82 @@ fold_builtin_is_corresponding_member (location_t loc, int nargs, tree *args)
 				   fold_convert (TREE_TYPE (arg1), arg2)));
 }
 
+// forked from gcc/cp/tree.cc lvalue_type
+
+/* The type of ARG when used as an lvalue.  */
+
+tree
+lvalue_type (tree arg)
+{
+  tree type = TREE_TYPE (arg);
+  return type;
+}
+
+// forked from gcc/c-family/c-warn.cc lvalue_error
+
+/* Print an error message for an invalid lvalue.  USE says
+   how the lvalue is being used and so selects the error message.  LOC
+   is the location for the error.  */
+
+void
+lvalue_error (location_t loc, enum lvalue_use use)
+{
+  switch (use)
+    {
+    case lv_assign:
+      error_at (loc, "lvalue required as left operand of assignment");
+      break;
+    case lv_increment:
+      error_at (loc, "lvalue required as increment operand");
+      break;
+    case lv_decrement:
+      error_at (loc, "lvalue required as decrement operand");
+      break;
+    case lv_addressof:
+      error_at (loc, "lvalue required as unary %<&%> operand");
+      break;
+    case lv_asm:
+      error_at (loc, "lvalue required in %<asm%> statement");
+      break;
+    default:
+      gcc_unreachable ();
+    }
+}
+
+// forked from gcc/cp/cp--gimplify.cc cp_fold_maybe_rvalue
+
+/* Fold expression X which is used as an rvalue if RVAL is true.  */
+
+tree
+cp_fold_maybe_rvalue (tree x, bool rval)
+{
+  while (true)
+    {
+      x = fold (x);
+      if (rval)
+	x = mark_rvalue_use (x);
+      if (rval && DECL_P (x) && !TYPE_REF_P (TREE_TYPE (x)))
+	{
+	  tree v = decl_constant_value (x);
+	  if (v != x && v != error_mark_node)
+	    {
+	      x = v;
+	      continue;
+	    }
+	}
+      break;
+    }
+  return x;
+}
+
+// forked from gcc/cp/cp--gimplify.cc cp_fold_rvalue
+
+/* Fold expression X which is used as an rvalue.  */
+
+tree
+cp_fold_rvalue (tree x)
+{
+  return cp_fold_maybe_rvalue (x, true);
+}
+
 } // namespace Rust
diff --git a/gcc/rust/backend/rust-tree.h b/gcc/rust/backend/rust-tree.h
index 57440af632d..524569a985e 100644
--- a/gcc/rust/backend/rust-tree.h
+++ b/gcc/rust/backend/rust-tree.h
@@ -1346,6 +1346,26 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX];
        of the enumeration is completed by finish_enum.  */
 #define ENUM_UNDERLYING_TYPE(TYPE) TREE_TYPE (ENUMERAL_TYPE_CHECK (TYPE))
 
+/* Nonzero if this type is volatile-qualified.  */
+#define CP_TYPE_VOLATILE_P(NODE)                                               \
+  ((rs_type_quals (NODE) & TYPE_QUAL_VOLATILE) != 0)
+
+/* Nonzero means that this type is either complete or being defined, so we
+   can do lookup in it.  */
+#define COMPLETE_OR_OPEN_TYPE_P(NODE)                                          \
+  (COMPLETE_TYPE_P (NODE) || (CLASS_TYPE_P (NODE) && TYPE_BEING_DEFINED (NODE)))
+
+/* Indicates when overload resolution may resolve to a pointer to
+   member function. [expr.unary.op]/3 */
+#define PTRMEM_OK_P(NODE)                                                      \
+  TREE_LANG_FLAG_0 (TREE_CHECK3 ((NODE), ADDR_EXPR, OFFSET_REF, SCOPE_REF))
+
+/* Returns nonzero iff NODE is a declaration for the global function
+   `main'.  */
+#define DECL_MAIN_P(NODE)                                                      \
+  (DECL_NAME (NODE) != NULL_TREE && MAIN_NAME_P (DECL_NAME (NODE))             \
+   && flag_hosted)
+
 #if defined ENABLE_TREE_CHECKING
 
 #define LANG_DECL_MIN_CHECK(NODE)                                              \
@@ -1512,6 +1532,77 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX];
 
 // Above macros are copied from gcc/cp/name-lookup.cc
 
+/* Places where an lvalue, or modifiable lvalue, may be required.
+   Used to select diagnostic messages in lvalue_error and
+   readonly_error.  */
+enum lvalue_use
+{
+  lv_assign,
+  lv_increment,
+  lv_decrement,
+  lv_addressof,
+  lv_asm
+};
+
+/* A class for recording information about access failures (e.g. private
+   fields), so that we can potentially supply a fix-it hint about
+   an accessor (from a context in which the constness of the object
+   is known).  */
+
+class access_failure_info
+{
+public:
+  access_failure_info ()
+    : m_was_inaccessible (false), m_basetype_path (NULL_TREE),
+      m_decl (NULL_TREE), m_diag_decl (NULL_TREE)
+  {}
+
+  void record_access_failure (tree basetype_path, tree decl, tree diag_decl);
+
+  bool was_inaccessible_p () const { return m_was_inaccessible; }
+  tree get_decl () const { return m_decl; }
+  tree get_diag_decl () const { return m_diag_decl; }
+  tree get_any_accessor (bool const_p) const;
+  void maybe_suggest_accessor (bool const_p) const;
+  static void add_fixit_hint (rich_location *richloc, tree accessor);
+
+private:
+  bool m_was_inaccessible;
+  tree m_basetype_path;
+  tree m_decl;
+  tree m_diag_decl;
+};
+
+/* The various kinds of access check during parsing.  */
+enum deferring_kind
+{
+  dk_no_deferred = 0, /* Check access immediately */
+  dk_deferred = 1,    /* Deferred check */
+  dk_no_check = 2     /* No access check */
+};
+
+/* The representation of a deferred access check.  */
+
+struct GTY (()) deferred_access_check
+{
+  /* The base class in which the declaration is referenced. */
+  tree binfo;
+  /* The declaration whose access must be checked.  */
+  tree decl;
+  /* The declaration that should be used in the error message.  */
+  tree diag_decl;
+  /* The location of this access.  */
+  location_t loc;
+};
+
+struct GTY (()) tree_template_info
+{
+  struct tree_base base;
+  tree tmpl;
+  tree args;
+  vec<deferred_access_check, va_gc> *deferred_access_checks;
+};
+
 /* The various kinds of lvalues we distinguish.  */
 enum cp_lvalue_kind_flags
 {
@@ -2819,6 +2910,18 @@ extern bool null_member_pointer_value_p (tree);
 extern tree
 fold_builtin_is_corresponding_member (location_t, int, tree *);
 
+extern tree cp_fold_rvalue (tree);
+
+extern tree
+maybe_constant_value (tree, tree = NULL_TREE, bool = false);
+
+extern tree lvalue_type (tree);
+
+extern void lvalue_error (location_t, enum lvalue_use);
+
+extern tree
+cp_fold_maybe_rvalue (tree, bool);
+
 // forked from gcc/cp/cp-tree.h
 
 enum
@@ -3043,6 +3146,8 @@ set_implicit_rvalue_p (tree ot)
 namespace Compile {
 extern tree
 maybe_constant_init (tree, tree = NULL_TREE, bool = false);
+
+extern bool potential_constant_expression (tree);
 }
 
 } // namespace Rust

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-08-29 15:35 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-29 15:35 [gcc/devel/rust/master] rust constexpr: port over cxx_eval_builtin_function_call() Thomas Schwinge

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).