LCOV - code coverage report
Current view: top level - gcc/rust/backend - rust-constexpr.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 35.4 % 2930 1036
Test Date: 2026-10-17 16:30:31 Functions: 54.2 % 107 58
Legend: Lines:     hit not hit

            Line data    Source code
       1              : // This file is part of GCC.
       2              : 
       3              : // GCC is free software; you can redistribute it and/or modify it under
       4              : // the terms of the GNU General Public License as published by the Free
       5              : // Software Foundation; either version 3, or (at your option) any later
       6              : // version.
       7              : 
       8              : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
       9              : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
      10              : // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      11              : // for more details.
      12              : 
      13              : // You should have received a copy of the GNU General Public License
      14              : // along with GCC; see the file COPYING3.  If not see
      15              : // <http://www.gnu.org/licenses/>.
      16              : 
      17              : #include "rust-constexpr.h"
      18              : #include "rust-location.h"
      19              : #include "rust-diagnostics.h"
      20              : #include "rust-tree.h"
      21              : #include "fold-const.h"
      22              : #include "realmpfr.h"
      23              : #include "convert.h"
      24              : #include "print-tree.h"
      25              : #include "tree-pretty-print.h"
      26              : #include "gimplify.h"
      27              : #include "tree-iterator.h"
      28              : #include "timevar.h"
      29              : #include "varasm.h"
      30              : #include "cgraph.h"
      31              : #include "tree-inline.h"
      32              : #include "vec.h"
      33              : #include "function.h"
      34              : #include "diagnostic.h"
      35              : #include "target.h"
      36              : #include "builtins.h"
      37              : 
      38              : #define VERIFY_CONSTANT(X)                                                     \
      39              :   do                                                                           \
      40              :     {                                                                          \
      41              :       if (verify_constant ((X), ctx->quiet, non_constant_p, overflow_p))       \
      42              :         return t;                                                              \
      43              :     }                                                                          \
      44              :   while (0)
      45              : 
      46              : namespace Rust {
      47              : namespace Compile {
      48              : 
      49              : /* Returns true iff FUN is an instantiation of a constexpr function
      50              :  template or a defaulted constexpr function.  */
      51              : 
      52              : bool
      53            0 : is_instantiation_of_constexpr (tree fun)
      54              : {
      55            0 :   return DECL_DECLARED_CONSTEXPR_P (fun);
      56              : }
      57              : 
      58              : /* Return true if T is a literal type.   */
      59              : 
      60              : bool
      61            0 : literal_type_p (tree t)
      62              : {
      63            0 :   if (SCALAR_TYPE_P (t) || VECTOR_TYPE_P (t) || TYPE_REF_P (t)
      64              :       || (VOID_TYPE_P (t)))
      65            0 :     return true;
      66              : 
      67              :   if (TREE_CODE (t) == ARRAY_TYPE)
      68            0 :     return literal_type_p (strip_array_types (t));
      69              :   return false;
      70              : }
      71              : 
      72              : static bool verify_constant (tree, bool, bool *, bool *);
      73              : 
      74              : static HOST_WIDE_INT find_array_ctor_elt (tree ary, tree dindex,
      75              :                                           bool insert = false);
      76              : static int array_index_cmp (tree key, tree index);
      77              : static bool potential_constant_expression_1 (tree t, bool want_rval,
      78              :                                              bool strict, bool now,
      79              :                                              tsubst_flags_t flags,
      80              :                                              tree *jump_target);
      81              : bool potential_constant_expression_1 (tree t, bool want_rval, bool strict,
      82              :                                       bool now, tsubst_flags_t flags);
      83              : tree unshare_constructor (tree t MEM_STAT_DECL);
      84              : void maybe_save_constexpr_fundef (tree fun);
      85              : 
      86              : static bool returns (tree *jump_target);
      87              : static bool breaks (tree *jump_target);
      88              : static bool continues (tree *jump_target);
      89              : static bool switches (tree *jump_target);
      90              : 
      91         5452 : struct constexpr_global_ctx
      92              : {
      93              :   /* Values for any temporaries or local variables within the
      94              :      constant-expression. */
      95              :   hash_map<tree, tree> values;
      96              :   /* Number of cxx_eval_constant_expression calls (except skipped ones,
      97              :      on simple constants or location wrappers) encountered during current
      98              :      cxx_eval_outermost_constant_expr call.  */
      99              :   HOST_WIDE_INT constexpr_ops_count;
     100              :   /* Heap VAR_DECLs created during the evaluation of the outermost constant
     101              :      expression.  */
     102              :   auto_vec<tree, 16> heap_vars;
     103              :   /* Cleanups that need to be evaluated at the end of CLEANUP_POINT_EXPR.  */
     104              :   vec<tree> *cleanups;
     105              :   /* If non-null, only allow modification of existing values of the variables
     106              :      in this set.  Set by modifiable_tracker, below.  */
     107              :   hash_set<tree> *modifiable;
     108              :   /* Number of heap VAR_DECL deallocations.  */
     109              :   unsigned heap_dealloc_count;
     110              :   /* Constructor.  */
     111         5452 :   constexpr_global_ctx ()
     112         5452 :     : constexpr_ops_count (0), cleanups (NULL), heap_dealloc_count (0)
     113         5452 :   {}
     114              : 
     115          151 :   tree get_value (tree t)
     116              :   {
     117          151 :     if (tree *p = values.get (t))
     118          150 :       if (*p != void_node)
     119          150 :         return *p;
     120              :     return NULL_TREE;
     121              :   }
     122              :   tree *get_value_ptr (tree t, bool initializing)
     123              :   {
     124              :     if (modifiable && !modifiable->contains (t))
     125              :       return nullptr;
     126              :     if (tree *p = values.get (t))
     127              :       {
     128              :         if (*p != void_node)
     129              :           return p;
     130              :         else if (initializing)
     131              :           {
     132              :             *p = NULL_TREE;
     133              :             return p;
     134              :           }
     135              :       }
     136              :     return nullptr;
     137              :   }
     138              :   void put_value (tree t, tree v)
     139              :   {
     140              :     bool already_in_map = values.put (t, v);
     141              :     if (!already_in_map && modifiable)
     142              :       modifiable->add (t);
     143              :   }
     144              :   void destroy_value (tree t)
     145              :   {
     146              :     if (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == PARM_DECL
     147              :         || TREE_CODE (t) == RESULT_DECL)
     148              :       values.put (t, void_node);
     149              :     else
     150              :       values.remove (t);
     151              :   }
     152              :   void clear_value (tree t) { values.remove (t); }
     153              : };
     154              : 
     155              : /* In constexpr.cc */
     156              : /* Representation of entries in the constexpr function definition table.  */
     157              : 
     158              : struct GTY ((for_user)) rust_constexpr_fundef
     159              : {
     160              :   tree decl;
     161              :   tree body;
     162              :   tree parms;
     163              :   tree result;
     164              : };
     165              : 
     166              : /* Objects of this type represent calls to constexpr functions
     167              :  along with the bindings of parameters to their arguments, for
     168              :  the purpose of compile time evaluation.  */
     169              : 
     170              : struct GTY ((for_user)) rust_constexpr_call
     171              : {
     172              :   /* Description of the constexpr function definition.  */
     173              :   rust_constexpr_fundef *fundef;
     174              :   /* Parameter bindings environment.  A TREE_VEC of arguments.  */
     175              :   tree bindings;
     176              :   /* Result of the call.
     177              :        NULL means the call is being evaluated.
     178              :        error_mark_node means that the evaluation was erroneous;
     179              :        otherwise, the actual value of the call.  */
     180              :   tree result;
     181              :   /* The hash of this call; we remember it here to avoid having to
     182              :      recalculate it when expanding the hash table.  */
     183              :   hashval_t hash;
     184              :   /* Whether __builtin_is_constant_evaluated() should evaluate to true.  */
     185              :   bool manifestly_const_eval;
     186              : };
     187              : 
     188              : struct rust_constexpr_call_hasher : ggc_ptr_hash<rust_constexpr_call>
     189              : {
     190              :   static hashval_t hash (rust_constexpr_call *);
     191              :   static bool equal (rust_constexpr_call *, rust_constexpr_call *);
     192              : };
     193              : 
     194              : enum constexpr_switch_state
     195              : {
     196              :   /* Used when processing a switch for the first time by cxx_eval_switch_expr
     197              :      and default: label for that switch has not been seen yet.  */
     198              :   css_default_not_seen,
     199              :   /* Used when processing a switch for the first time by cxx_eval_switch_expr
     200              :      and default: label for that switch has been seen already.  */
     201              :   css_default_seen,
     202              :   /* Used when processing a switch for the second time by
     203              :      cxx_eval_switch_expr, where default: label should match.  */
     204              :   css_default_processing
     205              : };
     206              : 
     207              : struct constexpr_ctx
     208              : {
     209              :   /* The part of the context that needs to be unique to the whole
     210              :      cxx_eval_outermost_constant_expr invocation.  */
     211              :   constexpr_global_ctx *global;
     212              :   /* The innermost call we're evaluating.  */
     213              :   rust_constexpr_call *call;
     214              :   /* SAVE_EXPRs and TARGET_EXPR_SLOT vars of TARGET_EXPRs that we've seen
     215              :      within the current LOOP_EXPR.  NULL if we aren't inside a loop.  */
     216              :   vec<tree> *save_exprs;
     217              :   /* The CONSTRUCTOR we're currently building up for an aggregate
     218              :      initializer.  */
     219              :   tree ctor;
     220              :   /* The object we're building the CONSTRUCTOR for.  */
     221              :   tree object;
     222              :   /* If inside SWITCH_EXPR.  */
     223              :   constexpr_switch_state *css_state;
     224              :   /* The aggregate initialization context inside which this one is nested.  This
     225              :      is used by lookup_placeholder to resolve PLACEHOLDER_EXPRs.  */
     226              :   const constexpr_ctx *parent;
     227              : 
     228              :   /* Whether we should error on a non-constant expression or fail quietly.
     229              :      This flag needs to be here, but some of the others could move to global
     230              :      if they get larger than a word.  */
     231              :   bool quiet;
     232              :   /* Whether we are strictly conforming to constant expression rules or
     233              :      trying harder to get a constant value.  */
     234              :   bool strict;
     235              :   /* Whether __builtin_is_constant_evaluated () should be true.  */
     236              :   bool manifestly_const_eval;
     237              : };
     238              : 
     239              : struct rust_constexpr_fundef_hasher : ggc_ptr_hash<rust_constexpr_fundef>
     240              : {
     241              :   static hashval_t hash (const rust_constexpr_fundef *);
     242              :   static bool equal (const rust_constexpr_fundef *,
     243              :                      const rust_constexpr_fundef *);
     244              : };
     245              : 
     246              : /* This table holds all constexpr function definitions seen in
     247              :    the current translation unit.  */
     248              : 
     249              : static GTY (())
     250              :   hash_table<rust_constexpr_fundef_hasher> *constexpr_fundef_table;
     251              : 
     252              : /* Utility function used for managing the constexpr function table.
     253              :    Return true if the entries pointed to by P and Q are for the
     254              :    same constexpr function.  */
     255              : 
     256              : inline bool
     257        10848 : rust_constexpr_fundef_hasher::equal (const rust_constexpr_fundef *lhs,
     258              :                                      const rust_constexpr_fundef *rhs)
     259              : {
     260        10848 :   return lhs->decl == rhs->decl;
     261              : }
     262              : 
     263              : /* Utility function used for managing the constexpr function table.
     264              :    Return a hash value for the entry pointed to by Q.  */
     265              : 
     266              : inline hashval_t
     267        18052 : rust_constexpr_fundef_hasher::hash (const rust_constexpr_fundef *fundef)
     268              : {
     269        18052 :   return DECL_UID (fundef->decl);
     270              : }
     271              : 
     272              : /* Return a previously saved definition of function FUN.   */
     273              : 
     274              : rust_constexpr_fundef *
     275         2405 : retrieve_constexpr_fundef (tree fun)
     276              : {
     277         2405 :   if (constexpr_fundef_table == NULL)
     278              :     return NULL;
     279              : 
     280         2405 :   rust_constexpr_fundef fundef = {fun, NULL_TREE, NULL_TREE, NULL_TREE};
     281         2405 :   return constexpr_fundef_table->find (&fundef);
     282              : }
     283              : 
     284              : /* This internal flag controls whether we should avoid doing anything during
     285              :    constexpr evaluation that would cause extra DECL_UID generation, such as
     286              :    template instantiation and function body copying.  */
     287              : 
     288              : static bool uid_sensitive_constexpr_evaluation_value;
     289              : 
     290              : /* An internal counter that keeps track of the number of times
     291              :    uid_sensitive_constexpr_evaluation_p returned true.  */
     292              : 
     293              : static unsigned uid_sensitive_constexpr_evaluation_true_counter;
     294              : 
     295              : /* The accessor for uid_sensitive_constexpr_evaluation_value which also
     296              :    increments the corresponding counter.  */
     297              : 
     298              : static bool
     299            0 : uid_sensitive_constexpr_evaluation_p ()
     300              : {
     301            0 :   if (uid_sensitive_constexpr_evaluation_value)
     302              :     {
     303            0 :       ++uid_sensitive_constexpr_evaluation_true_counter;
     304            0 :       return true;
     305              :     }
     306              :   else
     307              :     return false;
     308              : }
     309              : 
     310              : /* RAII sentinel that saves the value of a variable, optionally
     311              :    overrides it right away, and restores its value when the sentinel
     312              :    id destructed.  */
     313              : 
     314              : template <typename T> class temp_override
     315              : {
     316              :   T &overridden_variable;
     317              :   T saved_value;
     318              : 
     319              : public:
     320            0 :   temp_override (T &var) : overridden_variable (var), saved_value (var) {}
     321            0 :   temp_override (T &var, T overrider)
     322            0 :     : overridden_variable (var), saved_value (var)
     323              :   {
     324            0 :     overridden_variable = overrider;
     325              :   }
     326            0 :   ~temp_override () { overridden_variable = saved_value; }
     327              : };
     328              : 
     329              : /* An RAII sentinel used to restrict constexpr evaluation so that it
     330              :    doesn't do anything that causes extra DECL_UID generation.  */
     331              : 
     332              : struct uid_sensitive_constexpr_evaluation_sentinel
     333              : {
     334              :   temp_override<bool> ovr;
     335              :   uid_sensitive_constexpr_evaluation_sentinel ();
     336              : };
     337              : 
     338              : /* Used to determine whether uid_sensitive_constexpr_evaluation_p was
     339              :    called and returned true, indicating that we've restricted constexpr
     340              :    evaluation in order to avoid UID generation.  We use this to control
     341              :    updates to the fold_cache and cv_cache.  */
     342              : 
     343              : struct uid_sensitive_constexpr_evaluation_checker
     344              : {
     345              :   const unsigned saved_counter;
     346              :   uid_sensitive_constexpr_evaluation_checker ();
     347              :   bool evaluation_restricted_p () const;
     348              : };
     349              : 
     350              : /* The default constructor for uid_sensitive_constexpr_evaluation_sentinel
     351              :    enables the internal flag for uid_sensitive_constexpr_evaluation_p
     352              :    during the lifetime of the sentinel object.  Upon its destruction, the
     353              :    previous value of uid_sensitive_constexpr_evaluation_p is restored.  */
     354              : 
     355            0 : uid_sensitive_constexpr_evaluation_sentinel ::
     356              :   uid_sensitive_constexpr_evaluation_sentinel ()
     357            0 :   : ovr (uid_sensitive_constexpr_evaluation_value, true)
     358            0 : {}
     359              : 
     360              : /* The default constructor for uid_sensitive_constexpr_evaluation_checker
     361              :    records the current number of times that uid_sensitive_constexpr_evaluation_p
     362              :    has been called and returned true.  */
     363              : 
     364            0 : uid_sensitive_constexpr_evaluation_checker ::
     365              :   uid_sensitive_constexpr_evaluation_checker ()
     366            0 :   : saved_counter (uid_sensitive_constexpr_evaluation_true_counter)
     367            0 : {}
     368              : 
     369              : /* Returns true iff uid_sensitive_constexpr_evaluation_p is true, and
     370              :    some constexpr evaluation was restricted due to u_s_c_e_p being called
     371              :    and returning true during the lifetime of this checker object.  */
     372              : 
     373              : bool
     374            0 : uid_sensitive_constexpr_evaluation_checker::evaluation_restricted_p () const
     375              : {
     376            0 :   return (uid_sensitive_constexpr_evaluation_value
     377            0 :           && saved_counter != uid_sensitive_constexpr_evaluation_true_counter);
     378              : }
     379              : 
     380              : /* A table of all constexpr calls that have been evaluated by the
     381              :    compiler in this translation unit.  */
     382              : 
     383              : static GTY (()) hash_table<rust_constexpr_call_hasher> *constexpr_call_table;
     384              : 
     385              : /* Compute a hash value for a constexpr call representation.  */
     386              : 
     387              : inline hashval_t
     388         3450 : rust_constexpr_call_hasher::hash (rust_constexpr_call *info)
     389              : {
     390         3450 :   return info->hash;
     391              : }
     392              : 
     393              : /* Return true if the objects pointed to by P and Q represent calls
     394              :    to the same constexpr function with the same arguments.
     395              :    Otherwise, return false.  */
     396              : 
     397              : bool
     398         1176 : rust_constexpr_call_hasher::equal (rust_constexpr_call *lhs,
     399              :                                    rust_constexpr_call *rhs)
     400              : {
     401         1176 :   if (lhs == rhs)
     402              :     return true;
     403         1176 :   if (lhs->hash != rhs->hash)
     404              :     return false;
     405            0 :   if (lhs->manifestly_const_eval != rhs->manifestly_const_eval)
     406              :     return false;
     407            0 :   if (!rust_constexpr_fundef_hasher::equal (lhs->fundef, rhs->fundef))
     408              :     return false;
     409            0 :   return rs_tree_equal (lhs->bindings, rhs->bindings);
     410              : }
     411              : 
     412              : /* Initialize the constexpr call table, if needed.  */
     413              : 
     414              : static void
     415         2405 : maybe_initialize_constexpr_call_table (void)
     416              : {
     417         2405 :   if (constexpr_call_table == NULL)
     418          634 :     constexpr_call_table
     419          634 :       = hash_table<rust_constexpr_call_hasher>::create_ggc (101);
     420         2405 : }
     421              : 
     422              : /* During constexpr CALL_EXPR evaluation, to avoid issues with sharing when
     423              :    a function happens to get called recursively, we unshare the callee
     424              :    function's body and evaluate this unshared copy instead of evaluating the
     425              :    original body.
     426              : 
     427              :    FUNDEF_COPIES_TABLE is a per-function freelist of these unshared function
     428              :    copies.  The underlying data structure of FUNDEF_COPIES_TABLE is a hash_map
     429              :    that's keyed off of the original FUNCTION_DECL and whose value is a
     430              :    TREE_LIST of this function's unused copies awaiting reuse.
     431              : 
     432              :    This is not GC-deletable to avoid GC affecting UID generation.  */
     433              : 
     434              : static GTY (()) decl_tree_map *fundef_copies_table;
     435              : 
     436              : /* Reuse a copy or create a new unshared copy of the function FUN.
     437              :    Return this copy.  We use a TREE_LIST whose PURPOSE is body, VALUE
     438              :    is parms, TYPE is result.  */
     439              : 
     440              : static tree
     441         2405 : get_fundef_copy (rust_constexpr_fundef *fundef)
     442              : {
     443         2405 :   tree copy;
     444         2405 :   bool existed;
     445         2405 :   tree *slot
     446         2405 :     = &(hash_map_safe_get_or_insert<hm_ggc> (fundef_copies_table, fundef->decl,
     447              :                                              &existed, 127));
     448              : 
     449         2405 :   if (!existed)
     450              :     {
     451              :       /* There is no cached function available, or in use.  We can use
     452              :          the function directly.  That the slot is now created records
     453              :          that this function is now in use.  */
     454         2401 :       copy = build_tree_list (fundef->body, fundef->parms);
     455         2401 :       TREE_TYPE (copy) = fundef->result;
     456              :     }
     457            4 :   else if (*slot == NULL_TREE)
     458              :     {
     459            0 :       if (uid_sensitive_constexpr_evaluation_p ())
     460            0 :         return NULL_TREE;
     461              : 
     462              :       /* We've already used the function itself, so make a copy.  */
     463            0 :       copy = build_tree_list (NULL, NULL);
     464            0 :       tree saved_body = DECL_SAVED_TREE (fundef->decl);
     465            0 :       tree saved_parms = DECL_ARGUMENTS (fundef->decl);
     466            0 :       tree saved_result = DECL_RESULT (fundef->decl);
     467            0 :       tree saved_fn = current_function_decl;
     468            0 :       DECL_SAVED_TREE (fundef->decl) = fundef->body;
     469            0 :       DECL_ARGUMENTS (fundef->decl) = fundef->parms;
     470            0 :       DECL_RESULT (fundef->decl) = fundef->result;
     471            0 :       current_function_decl = fundef->decl;
     472            0 :       TREE_PURPOSE (copy)
     473            0 :         = copy_fn (fundef->decl, TREE_VALUE (copy), TREE_TYPE (copy));
     474            0 :       current_function_decl = saved_fn;
     475            0 :       DECL_RESULT (fundef->decl) = saved_result;
     476            0 :       DECL_ARGUMENTS (fundef->decl) = saved_parms;
     477            0 :       DECL_SAVED_TREE (fundef->decl) = saved_body;
     478              :     }
     479              :   else
     480              :     {
     481              :       /* We have a cached function available.  */
     482            4 :       copy = *slot;
     483            4 :       *slot = TREE_CHAIN (copy);
     484              :     }
     485              : 
     486              :   return copy;
     487              : }
     488              : 
     489              : /* Save the copy COPY of function FUN for later reuse by
     490              :    get_fundef_copy().  By construction, there will always be an entry
     491              :    to find.  */
     492              : 
     493              : static void
     494         2405 : save_fundef_copy (tree fun, tree copy)
     495              : {
     496         2405 :   tree *slot = fundef_copies_table->get (fun);
     497         2405 :   TREE_CHAIN (copy) = *slot;
     498         2405 :   *slot = copy;
     499         2405 : }
     500              : 
     501              : static tree constant_value_1 (tree decl, bool strict_p,
     502              :                               bool return_aggregate_cst_ok_p, bool unshare_p);
     503              : static tree decl_really_constant_value (tree decl, bool unshare_p /*= true*/);
     504              : tree decl_constant_value (tree decl, bool unshare_p);
     505              : 
     506              : static void non_const_var_error (location_t loc, tree r);
     507              : 
     508              : static tree eval_constant_expression (const constexpr_ctx *ctx, tree, bool,
     509              :                                       bool *, bool *, tree *jump_target);
     510              : 
     511              : static tree constexpr_fn_retval (const constexpr_ctx *ctx, tree r);
     512              : 
     513              : static tree eval_store_expression (const constexpr_ctx *ctx, tree r, bool,
     514              :                                    bool *, bool *, tree *jump_target);
     515              : 
     516              : static tree eval_call_expression (const constexpr_ctx *ctx, tree r, bool,
     517              :                                   bool *, bool *, tree *);
     518              : 
     519              : static tree eval_binary_expression (const constexpr_ctx *ctx, tree r, bool,
     520              :                                     bool *, bool *, tree *jump_target);
     521              : 
     522              : static tree get_function_named_in_call (tree t);
     523              : 
     524              : static tree eval_statement_list (const constexpr_ctx *ctx, tree t,
     525              :                                  bool *non_constant_p, bool *overflow_p,
     526              :                                  tree *jump_target);
     527              : static tree extract_string_elt (tree string, unsigned chars_per_elt,
     528              :                                 unsigned index);
     529              : 
     530              : static tree eval_conditional_expression (const constexpr_ctx *ctx, tree t,
     531              :                                          bool lval, bool *non_constant_p,
     532              :                                          bool *overflow_p, tree *jump_target);
     533              : 
     534              : static tree eval_bit_field_ref (const constexpr_ctx *ctx, tree t, bool lval,
     535              :                                 bool *non_constant_p, bool *overflow_p,
     536              :                                 tree *jump_target);
     537              : 
     538              : static tree eval_loop_expr (const constexpr_ctx *ctx, tree t,
     539              :                             bool *non_constant_p, bool *overflow_p,
     540              :                             tree *jump_target);
     541              : 
     542              : static tree eval_switch_expr (const constexpr_ctx *ctx, tree t,
     543              :                               bool *non_constant_p, bool *overflow_p,
     544              :                               tree *jump_target);
     545              : 
     546              : static tree eval_unary_expression (const constexpr_ctx *ctx, tree t,
     547              :                                    bool /*lval*/, bool *non_constant_p,
     548              :                                    bool *overflow_p, tree *jump_target);
     549              : static bool eval_check_shift_p (location_t loc, const constexpr_ctx *ctx,
     550              :                                 enum tree_code code, tree type, tree lhs,
     551              :                                 tree rhs);
     552              : static bool eval_check_overflow_p (location_t loc, const constexpr_ctx *ctx,
     553              :                                    enum tree_code code, tree type, tree lhs,
     554              :                                    tree rhs);
     555              : static tree fold_pointer_plus_expression (const constexpr_ctx *ctx, tree t,
     556              :                                           tree lhs, tree rhs,
     557              :                                           bool *non_constant_p,
     558              :                                           bool *overflow_p, tree *jump_target);
     559              : static tree maybe_fold_addr_pointer_plus (tree t);
     560              : static tree maybe_fold_reference_address_to_pointer (tree t);
     561              : 
     562              : /* Variables and functions to manage constexpr call expansion context.
     563              :    These do not need to be marked for PCH or GC.  */
     564              : 
     565              : /* FIXME remember and print actual constant arguments.  */
     566              : static vec<tree> call_stack;
     567              : static int call_stack_tick;
     568              : static int last_cx_error_tick;
     569              : 
     570              : static int
     571         2405 : push_cx_call_context (tree call)
     572              : {
     573         2405 :   ++call_stack_tick;
     574         2405 :   if (!EXPR_HAS_LOCATION (call))
     575          317 :     SET_EXPR_LOCATION (call, input_location);
     576         2405 :   call_stack.safe_push (call);
     577         2405 :   int len = call_stack.length ();
     578         2405 :   if (len > max_constexpr_depth)
     579            0 :     return false;
     580              :   return len;
     581              : }
     582              : 
     583              : static void
     584         2405 : pop_cx_call_context (void)
     585              : {
     586         2405 :   ++call_stack_tick;
     587         2405 :   call_stack.pop ();
     588         2405 : }
     589              : 
     590              : vec<tree>
     591            0 : cx_error_context (void)
     592              : {
     593            0 :   vec<tree> r = vNULL;
     594            0 :   if (call_stack_tick != last_cx_error_tick && !call_stack.is_empty ())
     595              :     r = call_stack;
     596            0 :   last_cx_error_tick = call_stack_tick;
     597            0 :   return r;
     598              : }
     599              : 
     600              : // this is ported from cxx_eval_outermost_constant_expr
     601              : tree
     602         5452 : fold_expr (tree expr)
     603              : {
     604         5452 :   bool allow_non_constant = false;
     605         5452 :   bool strict = true;
     606         5452 :   bool manifestly_const_eval = false;
     607              : 
     608         5452 :   constexpr_global_ctx global_ctx;
     609         5452 :   constexpr_ctx ctx
     610              :     = {&global_ctx, NULL,
     611              :        NULL,        NULL,
     612              :        NULL,        NULL,
     613              :        NULL,        allow_non_constant,
     614         5452 :        strict,      manifestly_const_eval || !allow_non_constant};
     615              : 
     616         5452 :   auto_vec<tree, 16> cleanups;
     617         5452 :   global_ctx.cleanups = &cleanups;
     618              : 
     619         5452 :   bool non_constant_p = false;
     620         5452 :   bool overflow_p = false;
     621              : 
     622         5452 :   tree jump_target = NULL_TREE;
     623         5452 :   tree folded = eval_constant_expression (&ctx, expr, false, &non_constant_p,
     624              :                                           &overflow_p, &jump_target);
     625         5452 :   rust_assert (folded != NULL_TREE);
     626              : 
     627              :   // more logic here to possibly port
     628         5452 :   return folded;
     629         5452 : }
     630              : 
     631              : static bool
     632           45 : same_type_ignoring_tlq_and_bounds_p (tree type1, tree type2)
     633              : {
     634           45 :   while (TREE_CODE (type1) == ARRAY_TYPE && TREE_CODE (type2) == ARRAY_TYPE
     635           45 :          && (!TYPE_DOMAIN (type1) || !TYPE_DOMAIN (type2)))
     636              :     {
     637            0 :       type1 = TREE_TYPE (type1);
     638            0 :       type2 = TREE_TYPE (type2);
     639              :     }
     640           45 :   return same_type_ignoring_top_level_qualifiers_p (type1, type2);
     641              : }
     642              : 
     643              : // forked from gcc/cp/constexpr.cc cxx_union_active_member
     644              : 
     645              : /* Try to determine the currently active union member for an expression
     646              :    with UNION_TYPE.  If it can be determined, return the FIELD_DECL,
     647              :    otherwise return NULL_TREE.  */
     648              : 
     649              : static tree
     650            0 : union_active_member (const constexpr_ctx *ctx, tree t, tree *jump_target)
     651              : {
     652            0 :   constexpr_ctx new_ctx = *ctx;
     653            0 :   new_ctx.quiet = true;
     654            0 :   bool non_constant_p = false, overflow_p = false;
     655            0 :   tree ctor = eval_constant_expression (&new_ctx, t, false, &non_constant_p,
     656              :                                         &overflow_p, jump_target);
     657            0 :   if (TREE_CODE (ctor) == CONSTRUCTOR && CONSTRUCTOR_NELTS (ctor) == 1
     658            0 :       && CONSTRUCTOR_ELT (ctor, 0)->index
     659            0 :       && TREE_CODE (CONSTRUCTOR_ELT (ctor, 0)->index) == FIELD_DECL)
     660              :     return CONSTRUCTOR_ELT (ctor, 0)->index;
     661              :   return NULL_TREE;
     662              : }
     663              : 
     664              : // forked from gcc/cp/constexpr.cc cxx_fold_indirect_ref_1
     665              : 
     666              : static tree
     667            0 : fold_indirect_ref_1 (const constexpr_ctx *ctx, location_t loc, tree type,
     668              :                      tree op, unsigned HOST_WIDE_INT off, bool *empty_base,
     669              :                      tree *jump_target)
     670              : {
     671            0 :   tree optype = TREE_TYPE (op);
     672            0 :   unsigned HOST_WIDE_INT const_nunits;
     673            0 :   if (off == 0 && similar_type_p (optype, type))
     674              :     return op;
     675            0 :   else if (TREE_CODE (optype) == COMPLEX_TYPE
     676            0 :            && similar_type_p (type, TREE_TYPE (optype)))
     677              :     {
     678              :       /* *(foo *)&complexfoo => __real__ complexfoo */
     679            0 :       if (off == 0)
     680            0 :         return build1_loc (loc, REALPART_EXPR, type, op);
     681              :       /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */
     682            0 :       else if (tree_to_uhwi (TYPE_SIZE_UNIT (type)) == off)
     683            0 :         return build1_loc (loc, IMAGPART_EXPR, type, op);
     684              :     }
     685              :   /* ((foo*)&vectorfoo)[x] => BIT_FIELD_REF<vectorfoo,...> */
     686            0 :   else if (VECTOR_TYPE_P (optype) && similar_type_p (type, TREE_TYPE (optype))
     687            0 :            && TYPE_VECTOR_SUBPARTS (optype).is_constant (&const_nunits))
     688              :     {
     689            0 :       unsigned HOST_WIDE_INT part_width = tree_to_uhwi (TYPE_SIZE_UNIT (type));
     690            0 :       unsigned HOST_WIDE_INT max_offset = part_width * const_nunits;
     691            0 :       if (off < max_offset && off % part_width == 0)
     692              :         {
     693            0 :           tree index = bitsize_int (off * BITS_PER_UNIT);
     694            0 :           return build3_loc (loc, BIT_FIELD_REF, type, op, TYPE_SIZE (type),
     695            0 :                              index);
     696              :         }
     697              :     }
     698              :   /* ((foo *)&fooarray)[x] => fooarray[x] */
     699            0 :   else if (TREE_CODE (optype) == ARRAY_TYPE
     700            0 :            && tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (optype)))
     701            0 :            && !integer_zerop (TYPE_SIZE_UNIT (TREE_TYPE (optype))))
     702              :     {
     703            0 :       tree type_domain = TYPE_DOMAIN (optype);
     704            0 :       tree min_val = size_zero_node;
     705            0 :       if (type_domain && TYPE_MIN_VALUE (type_domain))
     706            0 :         min_val = TYPE_MIN_VALUE (type_domain);
     707            0 :       unsigned HOST_WIDE_INT el_sz
     708            0 :         = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (optype)));
     709            0 :       unsigned HOST_WIDE_INT idx = off / el_sz;
     710            0 :       unsigned HOST_WIDE_INT rem = off % el_sz;
     711            0 :       if (tree_fits_uhwi_p (min_val))
     712              :         {
     713            0 :           tree index = size_int (idx + tree_to_uhwi (min_val));
     714            0 :           op = build4_loc (loc, ARRAY_REF, TREE_TYPE (optype), op, index,
     715              :                            NULL_TREE, NULL_TREE);
     716            0 :           return fold_indirect_ref_1 (ctx, loc, type, op, rem, empty_base,
     717            0 :                                       jump_target);
     718              :         }
     719              :     }
     720              :   /* ((foo *)&struct_with_foo_field)[x] => COMPONENT_REF */
     721            0 :   else if (TREE_CODE (optype) == RECORD_TYPE
     722            0 :            || TREE_CODE (optype) == UNION_TYPE)
     723              :     {
     724            0 :       if (TREE_CODE (optype) == UNION_TYPE)
     725              :         /* For unions prefer the currently active member.  */
     726            0 :         if (tree field = union_active_member (ctx, op, jump_target))
     727              :           {
     728            0 :             unsigned HOST_WIDE_INT el_sz
     729            0 :               = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (field)));
     730            0 :             if (off < el_sz)
     731              :               {
     732            0 :                 tree cop = build3 (COMPONENT_REF, TREE_TYPE (field), op, field,
     733              :                                    NULL_TREE);
     734            0 :                 if (tree ret = fold_indirect_ref_1 (ctx, loc, type, cop, off,
     735              :                                                     empty_base, jump_target))
     736              :                   return ret;
     737              :               }
     738              :           }
     739            0 :       for (tree field = TYPE_FIELDS (optype); field; field = DECL_CHAIN (field))
     740            0 :         if (TREE_CODE (field) == FIELD_DECL
     741            0 :             && TREE_TYPE (field) != error_mark_node
     742            0 :             && tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (field))))
     743              :           {
     744            0 :             tree pos = byte_position (field);
     745            0 :             if (!tree_fits_uhwi_p (pos))
     746            0 :               continue;
     747            0 :             unsigned HOST_WIDE_INT upos = tree_to_uhwi (pos);
     748            0 :             unsigned HOST_WIDE_INT el_sz
     749            0 :               = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (field)));
     750            0 :             if (upos <= off && off < upos + el_sz)
     751              :               {
     752            0 :                 tree cop = build3 (COMPONENT_REF, TREE_TYPE (field), op, field,
     753              :                                    NULL_TREE);
     754            0 :                 if (tree ret
     755            0 :                     = fold_indirect_ref_1 (ctx, loc, type, cop, off - upos,
     756              :                                            empty_base, jump_target))
     757              :                   return ret;
     758              :               }
     759              :           }
     760              :       /* Also handle conversion to an empty base class, which
     761              :          is represented with a NOP_EXPR.  */
     762            0 :       if (is_empty_class (type) && CLASS_TYPE_P (optype))
     763              :         {
     764            0 :           *empty_base = true;
     765            0 :           return op;
     766              :         }
     767              :     }
     768              : 
     769              :   return NULL_TREE;
     770              : }
     771              : 
     772              : // forked from gcc/cp/constexpr.cc cxx_fold_indirect_ref
     773              : 
     774              : /* A less strict version of fold_indirect_ref_1, which requires cv-quals to
     775              :    match.  We want to be less strict for simple *& folding; if we have a
     776              :    non-const temporary that we access through a const pointer, that should
     777              :    work.  We handle this here rather than change fold_indirect_ref_1
     778              :    because we're dealing with things like ADDR_EXPR of INTEGER_CST which
     779              :    don't really make sense outside of constant expression evaluation.  Also
     780              :    we want to allow folding to COMPONENT_REF, which could cause trouble
     781              :    with TBAA in fold_indirect_ref_1.  */
     782              : 
     783              : static tree
     784            4 : rs_fold_indirect_ref (const constexpr_ctx *ctx, location_t loc, tree type,
     785              :                       tree op0, bool *empty_base, tree *jump_target)
     786              : {
     787            4 :   tree sub = op0;
     788            4 :   tree subtype;
     789              : 
     790              :   /* STRIP_NOPS, but stop if REINTERPRET_CAST_P.  */
     791            8 :   while (CONVERT_EXPR_P (sub) || TREE_CODE (sub) == NON_LVALUE_EXPR
     792           11 :          || TREE_CODE (sub) == VIEW_CONVERT_EXPR)
     793              :     {
     794            3 :       if (TREE_CODE (sub) == NOP_EXPR && REINTERPRET_CAST_P (sub))
     795              :         return NULL_TREE;
     796            3 :       sub = TREE_OPERAND (sub, 0);
     797              :     }
     798              : 
     799            4 :   subtype = TREE_TYPE (sub);
     800            4 :   if (!INDIRECT_TYPE_P (subtype))
     801              :     return NULL_TREE;
     802              : 
     803              :   /* Canonicalizes the given OBJ/OFF pair by iteratively absorbing
     804              :      the innermost component into the offset until it would make the
     805              :      offset positive, so that cxx_fold_indirect_ref_1 can identify
     806              :      more folding opportunities.  */
     807            4 :   auto canonicalize_obj_off = [] (tree &obj, tree &off) {
     808            0 :     while (TREE_CODE (obj) == COMPONENT_REF
     809            0 :            && (tree_int_cst_sign_bit (off) || integer_zerop (off)))
     810              :       {
     811            0 :         tree field = TREE_OPERAND (obj, 1);
     812            0 :         tree pos = byte_position (field);
     813            0 :         if (integer_zerop (off) && integer_nonzerop (pos))
     814              :           /* If the offset is already 0, keep going as long as the
     815              :              component is at position 0.  */
     816              :           break;
     817            0 :         off = int_const_binop (PLUS_EXPR, off, pos);
     818            0 :         obj = TREE_OPERAND (obj, 0);
     819              :       }
     820            0 :   };
     821              : 
     822            4 :   if (TREE_CODE (sub) == ADDR_EXPR)
     823              :     {
     824            3 :       tree op = TREE_OPERAND (sub, 0);
     825            3 :       tree optype = TREE_TYPE (op);
     826              : 
     827              :       /* *&CONST_DECL -> to the value of the const decl.  */
     828            3 :       if (TREE_CODE (op) == CONST_DECL)
     829            0 :         return DECL_INITIAL (op);
     830              :       /* *&p => p;  make sure to handle *&"str"[cst] here.  */
     831            3 :       if (similar_type_p (optype, type))
     832              :         {
     833            3 :           tree fop = fold_read_from_constant_string (op);
     834            3 :           if (fop)
     835              :             return fop;
     836              :           else
     837            3 :             return op;
     838              :         }
     839              :       else
     840              :         {
     841            0 :           tree off = integer_zero_node;
     842            0 :           canonicalize_obj_off (op, off);
     843            0 :           gcc_assert (integer_zerop (off));
     844            0 :           return fold_indirect_ref_1 (ctx, loc, type, op, 0, empty_base,
     845              :                                       jump_target);
     846              :         }
     847              :     }
     848            1 :   else if (TREE_CODE (sub) == POINTER_PLUS_EXPR
     849            1 :            && tree_fits_uhwi_p (TREE_OPERAND (sub, 1)))
     850              :     {
     851            0 :       tree op00 = TREE_OPERAND (sub, 0);
     852            0 :       tree off = TREE_OPERAND (sub, 1);
     853              : 
     854            0 :       STRIP_NOPS (op00);
     855            0 :       if (TREE_CODE (op00) == ADDR_EXPR)
     856              :         {
     857            0 :           tree obj = TREE_OPERAND (op00, 0);
     858            0 :           canonicalize_obj_off (obj, off);
     859            0 :           return fold_indirect_ref_1 (ctx, loc, type, obj, tree_to_uhwi (off),
     860              :                                       empty_base, jump_target);
     861              :         }
     862              :     }
     863              :   /* *(foo *)fooarrptr => (*fooarrptr)[0] */
     864            1 :   else if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE
     865            1 :            && similar_type_p (type, TREE_TYPE (TREE_TYPE (subtype))))
     866              :     {
     867            0 :       tree type_domain;
     868            0 :       tree min_val = size_zero_node;
     869            0 :       tree newsub = rs_fold_indirect_ref (ctx, loc, TREE_TYPE (subtype), sub,
     870              :                                           NULL, jump_target);
     871            0 :       if (newsub)
     872              :         sub = newsub;
     873              :       else
     874            0 :         sub = build1_loc (loc, INDIRECT_REF, TREE_TYPE (subtype), sub);
     875            0 :       type_domain = TYPE_DOMAIN (TREE_TYPE (sub));
     876            0 :       if (type_domain && TYPE_MIN_VALUE (type_domain))
     877            0 :         min_val = TYPE_MIN_VALUE (type_domain);
     878            0 :       return build4_loc (loc, ARRAY_REF, type, sub, min_val, NULL_TREE,
     879            0 :                          NULL_TREE);
     880              :     }
     881              : 
     882              :   return NULL_TREE;
     883              : }
     884              : 
     885              : // forked from gcc/cp/constexpr.cc cxx_eval_indirect_ref
     886              : 
     887              : static tree
     888            3 : rs_eval_indirect_ref (const constexpr_ctx *ctx, tree t, bool lval,
     889              :                       bool *non_constant_p, bool *overflow_p, tree *jump_target)
     890              : {
     891            3 :   tree orig_op0 = TREE_OPERAND (t, 0);
     892            3 :   bool empty_base = false;
     893              : 
     894              :   /* We can handle a MEM_REF like an INDIRECT_REF, if MEM_REF's second
     895              :      operand is an integer-zero.  Otherwise reject the MEM_REF for now.  */
     896              : 
     897            3 :   if (TREE_CODE (t) == MEM_REF
     898            3 :       && (!TREE_OPERAND (t, 1) || !integer_zerop (TREE_OPERAND (t, 1))))
     899              :     {
     900            0 :       gcc_assert (ctx->quiet);
     901            0 :       *non_constant_p = true;
     902            0 :       return t;
     903              :     }
     904              : 
     905              :   /* First try to simplify it directly.  */
     906            3 :   tree r = rs_fold_indirect_ref (ctx, EXPR_LOCATION (t), TREE_TYPE (t),
     907              :                                  orig_op0, &empty_base, jump_target);
     908            3 :   if (!r)
     909              :     {
     910              :       /* If that didn't work, evaluate the operand first.  */
     911            1 :       tree op0 = eval_constant_expression (ctx, orig_op0,
     912              :                                            /*lval*/ false, non_constant_p,
     913              :                                            overflow_p, jump_target);
     914              :       /* Don't VERIFY_CONSTANT here.  */
     915            1 :       if (*non_constant_p)
     916              :         return t;
     917              : 
     918            1 :       if (!lval && integer_zerop (op0))
     919              :         {
     920            0 :           if (!ctx->quiet)
     921            0 :             error ("dereferencing a null pointer");
     922            0 :           *non_constant_p = true;
     923            0 :           return t;
     924              :         }
     925              : 
     926            1 :       r = rs_fold_indirect_ref (ctx, EXPR_LOCATION (t), TREE_TYPE (t), op0,
     927              :                                 &empty_base, jump_target);
     928            1 :       if (r == NULL_TREE)
     929              :         {
     930              :           /* We couldn't fold to a constant value.  Make sure it's not
     931              :              something we should have been able to fold.  */
     932            0 :           tree sub = op0;
     933            0 :           STRIP_NOPS (sub);
     934            0 :           if (TREE_CODE (sub) == ADDR_EXPR)
     935              :             {
     936            0 :               gcc_assert (
     937              :                 !similar_type_p (TREE_TYPE (TREE_TYPE (sub)), TREE_TYPE (t)));
     938              :               /* DR 1188 says we don't have to deal with this.  */
     939            0 :               if (!ctx->quiet)
     940            0 :                 error_at (rs_expr_loc_or_input_loc (t),
     941              :                           "accessing value of %qE through a %qT glvalue in a "
     942              :                           "constant expression",
     943            0 :                           build_fold_indirect_ref (sub), TREE_TYPE (t));
     944            0 :               *non_constant_p = true;
     945            0 :               return t;
     946              :             }
     947              : 
     948            0 :           if (lval && op0 != orig_op0)
     949            0 :             return build1 (INDIRECT_REF, TREE_TYPE (t), op0);
     950            0 :           if (!lval)
     951            0 :             VERIFY_CONSTANT (t);
     952              :           return t;
     953              :         }
     954              :     }
     955              : 
     956            3 :   r = eval_constant_expression (ctx, r, lval, non_constant_p, overflow_p,
     957              :                                 jump_target);
     958            3 :   if (*non_constant_p)
     959              :     return t;
     960              : 
     961              :   /* If we're pulling out the value of an empty base, just return an empty
     962              :      CONSTRUCTOR.  */
     963            3 :   if (empty_base && !lval)
     964              :     {
     965            0 :       r = build_constructor (TREE_TYPE (t), NULL);
     966            0 :       TREE_CONSTANT (r) = true;
     967              :     }
     968              : 
     969              :   return r;
     970              : }
     971              : 
     972              : // forked from gcc/cp/constexpr.cc cxx_eval_logical_expression
     973              : 
     974              : /* Subroutine of cxx_eval_constant_expression.
     975              :    Evaluate a short-circuited logical expression T in the context
     976              :    of a given constexpr CALL.  BAILOUT_VALUE is the value for
     977              :    early return.  CONTINUE_VALUE is used here purely for
     978              :    sanity check purposes.  */
     979              : 
     980              : static tree
     981            0 : eval_logical_expression (const constexpr_ctx *ctx, tree t, tree bailout_value,
     982              :                          tree continue_value, bool lval, bool *non_constant_p,
     983              :                          bool *overflow_p, tree *jump_target)
     984              : {
     985            0 :   tree r;
     986            0 :   tree lhs = eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval,
     987              :                                        non_constant_p, overflow_p, jump_target);
     988            0 :   VERIFY_CONSTANT (lhs);
     989            0 :   if (tree_int_cst_equal (lhs, bailout_value))
     990              :     return lhs;
     991            0 :   gcc_assert (tree_int_cst_equal (lhs, continue_value));
     992            0 :   r = eval_constant_expression (ctx, TREE_OPERAND (t, 1), lval, non_constant_p,
     993              :                                 overflow_p, jump_target);
     994            0 :   VERIFY_CONSTANT (r);
     995              :   return r;
     996              : }
     997              : 
     998              : // forked from gcc/cp/constexp.rcc lookup_placeholder
     999              : 
    1000              : /* Find the object of TYPE under initialization in CTX.  */
    1001              : 
    1002              : static tree
    1003            0 : lookup_placeholder (const constexpr_ctx *ctx, bool lval, tree type)
    1004              : {
    1005            0 :   if (!ctx)
    1006              :     return NULL_TREE;
    1007              : 
    1008              :   /* Prefer the outermost matching object, but don't cross
    1009              :      CONSTRUCTOR_PLACEHOLDER_BOUNDARY constructors.  */
    1010            0 :   if (ctx->ctor && !CONSTRUCTOR_PLACEHOLDER_BOUNDARY (ctx->ctor))
    1011            0 :     if (tree outer_ob = lookup_placeholder (ctx->parent, lval, type))
    1012              :       return outer_ob;
    1013              : 
    1014              :   /* We could use ctx->object unconditionally, but using ctx->ctor when we
    1015              :      can is a minor optimization.  */
    1016            0 :   if (!lval && ctx->ctor && same_type_p (TREE_TYPE (ctx->ctor), type))
    1017            0 :     return ctx->ctor;
    1018              : 
    1019            0 :   if (!ctx->object)
    1020              :     return NULL_TREE;
    1021              : 
    1022              :   /* Since an object cannot have a field of its own type, we can search outward
    1023              :      from ctx->object to find the unique containing object of TYPE.  */
    1024              :   tree ob = ctx->object;
    1025            0 :   while (ob)
    1026              :     {
    1027            0 :       if (same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (ob), type))
    1028              :         break;
    1029            0 :       if (handled_component_p (ob))
    1030            0 :         ob = TREE_OPERAND (ob, 0);
    1031              :       else
    1032              :         ob = NULL_TREE;
    1033              :     }
    1034              : 
    1035              :   return ob;
    1036              : }
    1037              : 
    1038              : // forked from gcc/cp/constexp.rcc inline_asm_in_constexpr_error
    1039              : 
    1040              : /* Complain about an attempt to evaluate inline assembly.  */
    1041              : 
    1042              : static void
    1043            0 : inline_asm_in_constexpr_error (location_t loc)
    1044              : {
    1045            0 :   auto_diagnostic_group d;
    1046            0 :   error_at (loc, "inline assembly is not a constant expression");
    1047            0 :   inform (loc, "only unevaluated inline assembly is allowed in a "
    1048              :                "%<constexpr%> function in C++20");
    1049            0 : }
    1050              : 
    1051              : // forked from gcc/cp/constexpr.cc verify_ctor_sanity
    1052              : 
    1053              : /* We're about to process an initializer for a class or array TYPE.  Make
    1054              :    sure that CTX is set up appropriately.  */
    1055              : 
    1056              : static void
    1057            2 : verify_ctor_sanity (const constexpr_ctx *ctx, tree type)
    1058              : {
    1059              :   /* We don't bother building a ctor for an empty base subobject.  */
    1060            2 :   if (is_empty_class (type))
    1061              :     return;
    1062              : 
    1063              :   /* We're in the middle of an initializer that might involve placeholders;
    1064              :      our caller should have created a CONSTRUCTOR for us to put the
    1065              :      initializer into.  We will either return that constructor or T.  */
    1066            2 :   gcc_assert (ctx->ctor);
    1067            2 :   gcc_assert (
    1068              :     same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE (ctx->ctor)));
    1069              :   /* We used to check that ctx->ctor was empty, but that isn't the case when
    1070              :      the object is zero-initialized before calling the constructor.  */
    1071            2 :   if (ctx->object)
    1072              :     {
    1073            1 :       tree otype = TREE_TYPE (ctx->object);
    1074            1 :       gcc_assert (same_type_ignoring_top_level_qualifiers_p (type, otype)
    1075              :                   /* Handle flexible array members.  */
    1076              :                   || (TREE_CODE (otype) == ARRAY_TYPE
    1077              :                       && TYPE_DOMAIN (otype) == NULL_TREE
    1078              :                       && TREE_CODE (type) == ARRAY_TYPE
    1079              :                       && (same_type_ignoring_top_level_qualifiers_p (
    1080              :                         TREE_TYPE (type), TREE_TYPE (otype)))));
    1081              :     }
    1082            2 :   gcc_assert (!ctx->object || !DECL_P (ctx->object)
    1083              :               || *(ctx->global->values.get (ctx->object)) == ctx->ctor);
    1084              : }
    1085              : 
    1086              : // forked from gcc/cp/constexpr.cc array_index_cmp
    1087              : 
    1088              : /* Some of the expressions fed to the constexpr mechanism are calls to
    1089              :    constructors, which have type void.  In that case, return the type being
    1090              :    initialized by the constructor.  */
    1091              : 
    1092              : static tree
    1093            3 : initialized_type (tree t)
    1094              : {
    1095            3 :   if (TYPE_P (t))
    1096              :     return t;
    1097            3 :   tree type = TREE_TYPE (t);
    1098            3 :   if (TREE_CODE (t) == CALL_EXPR)
    1099              :     {
    1100              :       /* A constructor call has void type, so we need to look deeper.  */
    1101            3 :       tree fn = get_function_named_in_call (t);
    1102            3 :       if (fn && TREE_CODE (fn) == FUNCTION_DECL && DECL_CXX_CONSTRUCTOR_P (fn))
    1103            0 :         type = DECL_CONTEXT (fn);
    1104              :     }
    1105            0 :   else if (TREE_CODE (t) == COMPOUND_EXPR)
    1106            0 :     return initialized_type (TREE_OPERAND (t, 1));
    1107              : 
    1108            3 :   return cv_unqualified (type);
    1109              : }
    1110              : 
    1111              : // forked from gcc/cp/constexpr.cc init_subob_ctx
    1112              : 
    1113              : /* We're about to initialize element INDEX of an array or class from VALUE.
    1114              :    Set up NEW_CTX appropriately by adjusting .object to refer to the
    1115              :    subobject and creating a new CONSTRUCTOR if the element is itself
    1116              :    a class or array.  */
    1117              : 
    1118              : static void
    1119            3 : init_subob_ctx (const constexpr_ctx *ctx, constexpr_ctx &new_ctx, tree index,
    1120              :                 tree &value)
    1121              : {
    1122            3 :   new_ctx = *ctx;
    1123              : 
    1124            3 :   if (index && TREE_CODE (index) != INTEGER_CST
    1125            2 :       && TREE_CODE (index) != FIELD_DECL && TREE_CODE (index) != RANGE_EXPR)
    1126              :     /* This won't have an element in the new CONSTRUCTOR.  */
    1127              :     return;
    1128              : 
    1129            3 :   tree type = initialized_type (value);
    1130            3 :   if (!AGGREGATE_TYPE_P (type) && !VECTOR_TYPE_P (type))
    1131              :     /* A non-aggregate member doesn't get its own CONSTRUCTOR.  */
    1132              :     return;
    1133              : 
    1134              :   /* The sub-aggregate initializer might contain a placeholder;
    1135              :      update object to refer to the subobject and ctor to refer to
    1136              :      the (newly created) sub-initializer.  */
    1137            1 :   if (ctx->object)
    1138              :     {
    1139            1 :       if (index == NULL_TREE || TREE_CODE (index) == RANGE_EXPR)
    1140              :         /* There's no well-defined subobject for this index.  */
    1141            0 :         new_ctx.object = NULL_TREE;
    1142              :       else
    1143              :         {
    1144              :           // Faisal: commenting this out as not sure if it's needed and it's
    1145              :           // huge new_ctx.object = build_ctor_subob_ref (index, type,
    1146              :           // ctx->object);
    1147              :         }
    1148              :     }
    1149            1 :   tree elt = build_constructor (type, NULL);
    1150            1 :   CONSTRUCTOR_NO_CLEARING (elt) = true;
    1151            1 :   new_ctx.ctor = elt;
    1152              : 
    1153            1 :   if (TREE_CODE (value) == TARGET_EXPR)
    1154              :     /* Avoid creating another CONSTRUCTOR when we expand the TARGET_EXPR.  */
    1155            0 :     value = TARGET_EXPR_INITIAL (value);
    1156              : }
    1157              : 
    1158              : // forked from gcc/cp/constexpr.cc base_field_constructor_elt
    1159              : 
    1160              : /* REF is a COMPONENT_REF designating a particular field.  V is a vector of
    1161              :    CONSTRUCTOR elements to initialize (part of) an object containing that
    1162              :    field.  Return a pointer to the constructor_elt corresponding to the
    1163              :    initialization of the field.  */
    1164              : 
    1165              : static constructor_elt *
    1166            0 : base_field_constructor_elt (vec<constructor_elt, va_gc> *v, tree ref)
    1167              : {
    1168            0 :   tree aggr = TREE_OPERAND (ref, 0);
    1169            0 :   tree field = TREE_OPERAND (ref, 1);
    1170            0 :   HOST_WIDE_INT i;
    1171            0 :   constructor_elt *ce;
    1172              : 
    1173            0 :   gcc_assert (TREE_CODE (ref) == COMPONENT_REF);
    1174              : 
    1175            0 :   if (TREE_CODE (aggr) == COMPONENT_REF)
    1176              :     {
    1177            0 :       constructor_elt *base_ce = base_field_constructor_elt (v, aggr);
    1178            0 :       v = CONSTRUCTOR_ELTS (base_ce->value);
    1179              :     }
    1180              : 
    1181            0 :   for (i = 0; vec_safe_iterate (v, i, &ce); ++i)
    1182            0 :     if (ce->index == field)
    1183            0 :       return ce;
    1184              : 
    1185            0 :   rust_unreachable ();
    1186              :   return NULL;
    1187              : }
    1188              : 
    1189              : /* Return a pointer to the constructor_elt of CTOR which matches INDEX.  If no
    1190              :    matching constructor_elt exists, then add one to CTOR.
    1191              : 
    1192              :    As an optimization, if POS_HINT is non-negative then it is used as a guess
    1193              :    for the (integer) index of the matching constructor_elt within CTOR.  */
    1194              : 
    1195              : static constructor_elt *
    1196            6 : get_or_insert_ctor_field (tree ctor, tree index, int pos_hint = -1)
    1197              : {
    1198              :   /* Check the hint first.  */
    1199            1 :   if (pos_hint >= 0 && (unsigned) pos_hint < CONSTRUCTOR_NELTS (ctor)
    1200            7 :       && CONSTRUCTOR_ELT (ctor, pos_hint)->index == index)
    1201              :     return CONSTRUCTOR_ELT (ctor, pos_hint);
    1202              : 
    1203            5 :   tree type = TREE_TYPE (ctor);
    1204            5 :   if (TREE_CODE (type) == VECTOR_TYPE && index == NULL_TREE)
    1205              :     {
    1206            0 :       CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (ctor), index, NULL_TREE);
    1207            0 :       return &CONSTRUCTOR_ELTS (ctor)->last ();
    1208              :     }
    1209            5 :   else if (TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == VECTOR_TYPE)
    1210              :     {
    1211            2 :       if (TREE_CODE (index) == RANGE_EXPR)
    1212              :         {
    1213              :           /* Support for RANGE_EXPR index lookups is currently limited to
    1214              :              accessing an existing element via POS_HINT, or appending a new
    1215              :              element to the end of CTOR.  ??? Support for other access
    1216              :              patterns may also be needed.  */
    1217            0 :           vec<constructor_elt, va_gc> *elts = CONSTRUCTOR_ELTS (ctor);
    1218            0 :           if (vec_safe_length (elts))
    1219              :             {
    1220            0 :               tree lo = TREE_OPERAND (index, 0);
    1221            0 :               gcc_assert (array_index_cmp (elts->last ().index, lo) < 0);
    1222              :             }
    1223            0 :           CONSTRUCTOR_APPEND_ELT (elts, index, NULL_TREE);
    1224            0 :           return &elts->last ();
    1225              :         }
    1226              : 
    1227            2 :       HOST_WIDE_INT i = find_array_ctor_elt (ctor, index, /*insert*/ true);
    1228            2 :       gcc_assert (i >= 0);
    1229            2 :       constructor_elt *cep = CONSTRUCTOR_ELT (ctor, i);
    1230            2 :       gcc_assert (cep->index == NULL_TREE
    1231              :                   || TREE_CODE (cep->index) != RANGE_EXPR);
    1232              :       return cep;
    1233              :     }
    1234              :   else
    1235              :     {
    1236            3 :       gcc_assert (
    1237              :         TREE_CODE (index) == FIELD_DECL
    1238              :         && (same_type_ignoring_top_level_qualifiers_p (DECL_CONTEXT (index),
    1239              :                                                        TREE_TYPE (ctor))));
    1240              : 
    1241              :       /* We must keep the CONSTRUCTOR's ELTS in FIELD order.
    1242              :          Usually we meet initializers in that order, but it is
    1243              :          possible for base types to be placed not in program
    1244              :          order.  */
    1245            3 :       tree fields = TYPE_FIELDS (DECL_CONTEXT (index));
    1246            3 :       unsigned HOST_WIDE_INT idx = 0;
    1247            3 :       constructor_elt *cep = NULL;
    1248              : 
    1249              :       /* Check if we're changing the active member of a union.  */
    1250            0 :       if (TREE_CODE (type) == UNION_TYPE && CONSTRUCTOR_NELTS (ctor)
    1251            3 :           && CONSTRUCTOR_ELT (ctor, 0)->index != index)
    1252            0 :         vec_safe_truncate (CONSTRUCTOR_ELTS (ctor), 0);
    1253              :       /* If the bit offset of INDEX is larger than that of the last
    1254              :          constructor_elt, then we can just immediately append a new
    1255              :          constructor_elt to the end of CTOR.  */
    1256            5 :       else if (CONSTRUCTOR_NELTS (ctor)
    1257            5 :                && tree_int_cst_compare (
    1258            2 :                     bit_position (index),
    1259            2 :                     bit_position (CONSTRUCTOR_ELTS (ctor)->last ().index))
    1260              :                     > 0)
    1261              :         {
    1262            1 :           idx = CONSTRUCTOR_NELTS (ctor);
    1263            1 :           goto insert;
    1264              :         }
    1265              : 
    1266              :       /* Otherwise, we need to iterate over CTOR to find or insert INDEX
    1267              :          appropriately.  */
    1268              : 
    1269            2 :       for (; vec_safe_iterate (CONSTRUCTOR_ELTS (ctor), idx, &cep);
    1270            0 :            idx++, fields = DECL_CHAIN (fields))
    1271              :         {
    1272            1 :           if (index == cep->index)
    1273            1 :             goto found;
    1274              : 
    1275              :           /* The field we're initializing must be on the field
    1276              :              list.  Look to see if it is present before the
    1277              :              field the current ELT initializes.  */
    1278            0 :           for (; fields != cep->index; fields = DECL_CHAIN (fields))
    1279            0 :             if (index == fields)
    1280            0 :               goto insert;
    1281              :         }
    1282              :       /* We fell off the end of the CONSTRUCTOR, so insert a new
    1283              :          entry at the end.  */
    1284              : 
    1285            2 :     insert:
    1286            2 :       {
    1287            2 :         constructor_elt ce = {index, NULL_TREE};
    1288              : 
    1289            2 :         vec_safe_insert (CONSTRUCTOR_ELTS (ctor), idx, ce);
    1290            2 :         cep = CONSTRUCTOR_ELT (ctor, idx);
    1291              :       }
    1292            6 :     found:;
    1293              : 
    1294              :       return cep;
    1295              :     }
    1296              : }
    1297              : 
    1298              : // forked from gcc/cp/constexpr.cc cxx_eval_vector_conditional_expression
    1299              : 
    1300              : /* Subroutine of cxx_eval_constant_expression.
    1301              :    Attempt to evaluate vector condition expressions.  Unlike
    1302              :    cxx_eval_conditional_expression, VEC_COND_EXPR acts like a normal
    1303              :    ternary arithmetics operation, where all 3 arguments have to be
    1304              :    evaluated as constants and then folding computes the result from
    1305              :    them.  */
    1306              : 
    1307              : static tree
    1308            0 : eval_vector_conditional_expression (const constexpr_ctx *ctx, tree t,
    1309              :                                     bool *non_constant_p, bool *overflow_p,
    1310              :                                     tree *jump_target)
    1311              : {
    1312            0 :   tree arg1 = eval_constant_expression (ctx, TREE_OPERAND (t, 0),
    1313              :                                         /*lval*/ false, non_constant_p,
    1314              :                                         overflow_p, jump_target);
    1315            0 :   VERIFY_CONSTANT (arg1);
    1316            0 :   tree arg2 = eval_constant_expression (ctx, TREE_OPERAND (t, 1),
    1317              :                                         /*lval*/ false, non_constant_p,
    1318              :                                         overflow_p, jump_target);
    1319            0 :   VERIFY_CONSTANT (arg2);
    1320            0 :   tree arg3 = eval_constant_expression (ctx, TREE_OPERAND (t, 2),
    1321              :                                         /*lval*/ false, non_constant_p,
    1322              :                                         overflow_p, jump_target);
    1323            0 :   VERIFY_CONSTANT (arg3);
    1324            0 :   location_t loc = EXPR_LOCATION (t);
    1325            0 :   tree type = TREE_TYPE (t);
    1326            0 :   tree r = fold_ternary_loc (loc, VEC_COND_EXPR, type, arg1, arg2, arg3);
    1327            0 :   if (r == NULL_TREE)
    1328              :     {
    1329            0 :       if (arg1 == TREE_OPERAND (t, 0) && arg2 == TREE_OPERAND (t, 1)
    1330            0 :           && arg3 == TREE_OPERAND (t, 2))
    1331              :         r = t;
    1332              :       else
    1333            0 :         r = build3_loc (loc, VEC_COND_EXPR, type, arg1, arg2, arg3);
    1334              :     }
    1335            0 :   VERIFY_CONSTANT (r);
    1336              :   return r;
    1337              : }
    1338              : 
    1339              : // forked from gcc/cp/constexpr.cc cxx_eval_bare_aggregate
    1340              : 
    1341              : /* Subroutine of cxx_eval_constant_expression.
    1342              :    The expression tree T denotes a C-style array or a C-style
    1343              :    aggregate.  Reduce it to a constant expression.  */
    1344              : 
    1345              : static tree
    1346            2 : eval_bare_aggregate (const constexpr_ctx *ctx, tree t, bool lval,
    1347              :                      bool *non_constant_p, bool *overflow_p, tree *jump_target)
    1348              : {
    1349            2 :   vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (t);
    1350            2 :   bool changed = false;
    1351            2 :   gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (t));
    1352            2 :   tree type = TREE_TYPE (t);
    1353              : 
    1354            2 :   constexpr_ctx new_ctx;
    1355            2 :   if (TYPE_PTRMEMFUNC_P (type) || VECTOR_TYPE_P (type))
    1356              :     {
    1357              :       /* We don't really need the ctx->ctor business for a PMF or
    1358              :          vector, but it's simpler to use the same code.  */
    1359            0 :       new_ctx = *ctx;
    1360            0 :       new_ctx.ctor = build_constructor (type, NULL);
    1361            0 :       new_ctx.object = NULL_TREE;
    1362            0 :       ctx = &new_ctx;
    1363            2 :     };
    1364            2 :   verify_ctor_sanity (ctx, type);
    1365            2 :   vec<constructor_elt, va_gc> **p = &CONSTRUCTOR_ELTS (ctx->ctor);
    1366            4 :   vec_alloc (*p, vec_safe_length (v));
    1367              : 
    1368            2 :   if (CONSTRUCTOR_PLACEHOLDER_BOUNDARY (t))
    1369            0 :     CONSTRUCTOR_PLACEHOLDER_BOUNDARY (ctx->ctor) = 1;
    1370              : 
    1371            2 :   unsigned i;
    1372            2 :   tree index, value;
    1373            2 :   bool constant_p = true;
    1374            2 :   bool side_effects_p = false;
    1375            5 :   FOR_EACH_CONSTRUCTOR_ELT (v, i, index, value)
    1376              :     {
    1377            3 :       tree orig_value = value;
    1378              :       /* Like in cxx_eval_store_expression, omit entries for empty fields.  */
    1379            3 :       bool no_slot = TREE_CODE (type) == RECORD_TYPE && is_empty_field (index);
    1380            3 :       if (no_slot)
    1381            0 :         new_ctx = *ctx;
    1382              :       else
    1383            3 :         init_subob_ctx (ctx, new_ctx, index, value);
    1384            3 :       int pos_hint = -1;
    1385            3 :       if (new_ctx.ctor != ctx->ctor)
    1386              :         {
    1387              :           /* If we built a new CONSTRUCTOR, attach it now so that other
    1388              :              initializers can refer to it.  */
    1389            1 :           constructor_elt *cep = get_or_insert_ctor_field (ctx->ctor, index);
    1390            1 :           cep->value = new_ctx.ctor;
    1391            1 :           pos_hint = cep - (*p)->begin ();
    1392              :         }
    1393            2 :       else if (TREE_CODE (type) == UNION_TYPE)
    1394              :         /* Otherwise if we're constructing a non-aggregate union member, set
    1395              :            the active union member now so that we can later detect and diagnose
    1396              :            if its initializer attempts to activate another member.  */
    1397            0 :         get_or_insert_ctor_field (ctx->ctor, index);
    1398            3 :       tree elt
    1399            3 :         = eval_constant_expression (&new_ctx, value, lval, non_constant_p,
    1400              :                                     overflow_p, jump_target);
    1401              :       /* Don't VERIFY_CONSTANT here.  */
    1402            3 :       if (ctx->quiet && *non_constant_p)
    1403              :         break;
    1404            3 :       if (elt != orig_value)
    1405            3 :         changed = true;
    1406              : 
    1407            3 :       if (!TREE_CONSTANT (elt))
    1408            0 :         constant_p = false;
    1409            3 :       if (TREE_SIDE_EFFECTS (elt))
    1410            0 :         side_effects_p = true;
    1411            3 :       if (index && TREE_CODE (index) == COMPONENT_REF)
    1412              :         {
    1413              :           /* This is an initialization of a vfield inside a base
    1414              :              subaggregate that we already initialized; push this
    1415              :              initialization into the previous initialization.  */
    1416            0 :           constructor_elt *inner = base_field_constructor_elt (*p, index);
    1417            0 :           inner->value = elt;
    1418            0 :           changed = true;
    1419            0 :         }
    1420            3 :       else if (index
    1421            3 :                && (TREE_CODE (index) == NOP_EXPR
    1422            3 :                    || TREE_CODE (index) == POINTER_PLUS_EXPR))
    1423              :         {
    1424              :           /* This is an initializer for an empty base; now that we've
    1425              :              checked that it's constant, we can ignore it.  */
    1426            0 :           gcc_assert (is_empty_class (TREE_TYPE (TREE_TYPE (index))));
    1427              :           changed = true;
    1428              :         }
    1429            3 :       else if (no_slot)
    1430              :         changed = true;
    1431              :       else
    1432              :         {
    1433            3 :           if (TREE_CODE (type) == UNION_TYPE && (*p)->last ().index != index)
    1434              :             /* The initializer erroneously changed the active union member that
    1435              :                we're initializing.  */
    1436            0 :             gcc_assert (*non_constant_p);
    1437              :           else
    1438              :             {
    1439              :               /* The initializer might have mutated the underlying CONSTRUCTOR,
    1440              :                  so recompute the location of the target constructer_elt.  */
    1441            3 :               constructor_elt *cep
    1442            3 :                 = get_or_insert_ctor_field (ctx->ctor, index, pos_hint);
    1443            3 :               cep->value = elt;
    1444              :             }
    1445              : 
    1446              :           /* Adding or replacing an element might change the ctor's flags.  */
    1447            3 :           TREE_CONSTANT (ctx->ctor) = constant_p;
    1448            3 :           TREE_SIDE_EFFECTS (ctx->ctor) = side_effects_p;
    1449              :         }
    1450              :     }
    1451            2 :   if (*non_constant_p || !changed)
    1452              :     return t;
    1453            2 :   t = ctx->ctor;
    1454              :   /* We're done building this CONSTRUCTOR, so now we can interpret an
    1455              :      element without an explicit initializer as value-initialized.  */
    1456            2 :   CONSTRUCTOR_NO_CLEARING (t) = false;
    1457            2 :   TREE_CONSTANT (t) = constant_p;
    1458            2 :   TREE_SIDE_EFFECTS (t) = side_effects_p;
    1459            2 :   if (VECTOR_TYPE_P (type))
    1460            0 :     t = fold (t);
    1461              :   return t;
    1462              : }
    1463              : 
    1464              : /* Subroutine of cxx_eval_constant_expression.
    1465              :    Like cxx_eval_unary_expression, except for trinary expressions.  */
    1466              : 
    1467              : static tree
    1468            0 : cxx_eval_trinary_expression (const constexpr_ctx *ctx, tree t, bool lval,
    1469              :                              bool *non_constant_p, bool *overflow_p,
    1470              :                              tree *jump_target)
    1471              : {
    1472            0 :   int i;
    1473            0 :   tree args[3];
    1474            0 :   tree val;
    1475              : 
    1476            0 :   for (i = 0; i < 3; i++)
    1477              :     {
    1478            0 :       args[i]
    1479            0 :         = eval_constant_expression (ctx, TREE_OPERAND (t, i), lval,
    1480              :                                     non_constant_p, overflow_p, jump_target);
    1481            0 :       VERIFY_CONSTANT (args[i]);
    1482              :     }
    1483              : 
    1484            0 :   val = fold_ternary_loc (EXPR_LOCATION (t), TREE_CODE (t), TREE_TYPE (t),
    1485              :                           args[0], args[1], args[2]);
    1486            0 :   if (val == NULL_TREE)
    1487              :     return t;
    1488            0 :   VERIFY_CONSTANT (val);
    1489              :   return val;
    1490              : }
    1491              : 
    1492              : /* Return true if T is a valid constant initializer.  If a CONSTRUCTOR
    1493              :    initializes all the members, the CONSTRUCTOR_NO_CLEARING flag will be
    1494              :    cleared.
    1495              :    FIXME speed this up, it's taking 16% of compile time on sieve testcase.  */
    1496              : 
    1497              : bool
    1498       263045 : reduced_constant_expression_p (tree t)
    1499              : {
    1500       263045 :   if (t == NULL_TREE)
    1501              :     return false;
    1502              : 
    1503       263045 :   switch (TREE_CODE (t))
    1504              :     {
    1505              :     case PTRMEM_CST:
    1506              :       /* Even if we can't lower this yet, it's constant.  */
    1507              :       return true;
    1508              : 
    1509           78 :     case CONSTRUCTOR:
    1510              :       /* And we need to handle PTRMEM_CST wrapped in a CONSTRUCTOR.  */
    1511           78 :       tree field;
    1512           78 :       if (CONSTRUCTOR_NO_CLEARING (t))
    1513              :         {
    1514            0 :           if (TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
    1515              :             /* An initialized vector would have a VECTOR_CST.  */
    1516              :             return false;
    1517            0 :           else if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
    1518              :             {
    1519              :               /* There must be a valid constant initializer at every array
    1520              :                  index.  */
    1521            0 :               tree min = TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (t)));
    1522            0 :               tree max = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (t)));
    1523            0 :               tree cursor = min;
    1524            0 :               for (auto &e : CONSTRUCTOR_ELTS (t))
    1525              :                 {
    1526            0 :                   if (!reduced_constant_expression_p (e.value))
    1527              :                     return false;
    1528            0 :                   if (array_index_cmp (cursor, e.index) != 0)
    1529              :                     return false;
    1530            0 :                   if (TREE_CODE (e.index) == RANGE_EXPR)
    1531            0 :                     cursor = TREE_OPERAND (e.index, 1);
    1532            0 :                   cursor = int_const_binop (PLUS_EXPR, cursor, size_one_node);
    1533              :                 }
    1534            0 :               if (find_array_ctor_elt (t, max) == -1)
    1535              :                 return false;
    1536            0 :               goto ok;
    1537              :             }
    1538            0 :           else if (TREE_CODE (TREE_TYPE (t)) == UNION_TYPE)
    1539              :             {
    1540            0 :               if (CONSTRUCTOR_NELTS (t) == 0)
    1541              :                 /* An initialized union has a constructor element.  */
    1542              :                 return false;
    1543              :               /* And it only initializes one member.  */
    1544              :               field = NULL_TREE;
    1545              :             }
    1546              :           else
    1547            0 :             field = next_initializable_field (TYPE_FIELDS (TREE_TYPE (t)));
    1548              :         }
    1549              :       else
    1550              :         field = NULL_TREE;
    1551          627 :       for (auto &e : CONSTRUCTOR_ELTS (t))
    1552              :         {
    1553              :           /* If VAL is null, we're in the middle of initializing this
    1554              :              element.  */
    1555          419 :           if (!reduced_constant_expression_p (e.value))
    1556              :             return false;
    1557              :           /* Empty class field may or may not have an initializer.  */
    1558          419 :           for (; field && e.index != field;
    1559            0 :                field = next_initializable_field (DECL_CHAIN (field)))
    1560            0 :             if (!is_really_empty_class (TREE_TYPE (field),
    1561              :                                         /*ignore_vptr*/ false))
    1562              :               return false;
    1563          419 :           if (field)
    1564            0 :             field = next_initializable_field (DECL_CHAIN (field));
    1565              :         }
    1566              :       /* There could be a non-empty field at the end.  */
    1567           78 :       for (; field; field = next_initializable_field (DECL_CHAIN (field)))
    1568            0 :         if (!is_really_empty_class (TREE_TYPE (field), /*ignore_vptr*/ false))
    1569              :           return false;
    1570           78 :     ok:
    1571           78 :       if (CONSTRUCTOR_NO_CLEARING (t))
    1572              :         /* All the fields are initialized.  */
    1573            0 :         CONSTRUCTOR_NO_CLEARING (t) = false;
    1574              :       return true;
    1575              : 
    1576       262967 :     default:
    1577              :       /* FIXME are we calling this too much?  */
    1578       262967 :       return initializer_constant_valid_p (t, TREE_TYPE (t)) != NULL_TREE;
    1579              :     }
    1580              : }
    1581              : 
    1582              : /* TEMP is the constant value of a temporary object of type TYPE.  Adjust
    1583              :    the type of the value to match.  */
    1584              : 
    1585              : static tree
    1586           14 : adjust_temp_type (tree type, tree temp)
    1587              : {
    1588           14 :   if (same_type_p (TREE_TYPE (temp), type))
    1589              :     return temp;
    1590              : 
    1591           12 :   if (TREE_CODE (temp) == CONSTRUCTOR)
    1592              :     {
    1593            1 :       tree t = copy_node (temp);
    1594            1 :       TREE_TYPE (t) = type;
    1595            1 :       return t;
    1596              :     }
    1597              : 
    1598           11 :   gcc_assert (scalarish_type_p (type));
    1599              :   /* Now we know we're dealing with a scalar, and a prvalue of non-class
    1600              :      type is cv-unqualified.  */
    1601           11 :   return fold_convert (cv_unqualified (type), temp);
    1602              : }
    1603              : 
    1604              : // forked from gcc/cp/constexpr.cc free_constructor
    1605              : 
    1606              : /* If T is a CONSTRUCTOR, ggc_free T and any sub-CONSTRUCTORs.  */
    1607              : 
    1608              : static void
    1609            0 : free_constructor (tree t)
    1610              : {
    1611            0 :   if (!t || TREE_CODE (t) != CONSTRUCTOR)
    1612            0 :     return;
    1613            0 :   releasing_vec ctors;
    1614            0 :   vec_safe_push (ctors, t);
    1615            0 :   while (!ctors->is_empty ())
    1616              :     {
    1617            0 :       tree c = ctors->pop ();
    1618            0 :       if (vec<constructor_elt, va_gc> *elts = CONSTRUCTOR_ELTS (c))
    1619              :         {
    1620              :           constructor_elt *ce;
    1621            0 :           for (HOST_WIDE_INT i = 0; vec_safe_iterate (elts, i, &ce); ++i)
    1622            0 :             if (TREE_CODE (ce->value) == CONSTRUCTOR)
    1623            0 :               vec_safe_push (ctors, ce->value);
    1624            0 :           ggc_free (elts);
    1625              :         }
    1626            0 :       ggc_free (c);
    1627              :     }
    1628            0 : }
    1629              : 
    1630              : static tree eval_and_check_array_index (const constexpr_ctx *ctx, tree t,
    1631              :                                         bool allow_one_past,
    1632              :                                         bool *non_constant_p, bool *overflow_p,
    1633              :                                         tree *jump_target);
    1634              : 
    1635              : // forked from gcc/cp/constexpr.cc cxx_eval_array_reference
    1636              : 
    1637              : /* Subroutine of cxx_eval_constant_expression.
    1638              :    Attempt to reduce a reference to an array slot.  */
    1639              : 
    1640              : static tree
    1641            9 : eval_array_reference (const constexpr_ctx *ctx, tree t, bool lval,
    1642              :                       bool *non_constant_p, bool *overflow_p, tree *jump_target)
    1643              : {
    1644            9 :   tree oldary = TREE_OPERAND (t, 0);
    1645            9 :   tree ary = eval_constant_expression (ctx, oldary, lval, non_constant_p,
    1646              :                                        overflow_p, jump_target);
    1647            9 :   if (*non_constant_p)
    1648              :     return t;
    1649            9 :   if (!lval && TREE_CODE (ary) == VIEW_CONVERT_EXPR
    1650            0 :       && VECTOR_TYPE_P (TREE_TYPE (TREE_OPERAND (ary, 0)))
    1651            9 :       && TREE_TYPE (t) == TREE_TYPE (TREE_TYPE (TREE_OPERAND (ary, 0))))
    1652            0 :     ary = TREE_OPERAND (ary, 0);
    1653              : 
    1654            9 :   tree oldidx = TREE_OPERAND (t, 1);
    1655            9 :   tree index = eval_and_check_array_index (ctx, t, lval, non_constant_p,
    1656              :                                            overflow_p, jump_target);
    1657            9 :   if (*non_constant_p)
    1658              :     return t;
    1659              : 
    1660            8 :   if (lval && ary == oldary && index == oldidx)
    1661              :     return t;
    1662            8 :   else if (lval)
    1663            0 :     return build4 (ARRAY_REF, TREE_TYPE (t), ary, index, NULL, NULL);
    1664              : 
    1665            8 :   unsigned len = 0, elem_nchars = 1;
    1666            8 :   tree elem_type = TREE_TYPE (TREE_TYPE (ary));
    1667            8 :   if (TREE_CODE (ary) == CONSTRUCTOR)
    1668            8 :     len = CONSTRUCTOR_NELTS (ary);
    1669            0 :   else if (TREE_CODE (ary) == STRING_CST)
    1670              :     {
    1671            0 :       elem_nchars
    1672            0 :         = (TYPE_PRECISION (elem_type) / TYPE_PRECISION (char_type_node));
    1673            0 :       len = (unsigned) TREE_STRING_LENGTH (ary) / elem_nchars;
    1674              :     }
    1675            0 :   else if (TREE_CODE (ary) == VECTOR_CST)
    1676              :     /* We don't create variable-length VECTOR_CSTs.  */
    1677            0 :     len = VECTOR_CST_NELTS (ary).to_constant ();
    1678              :   else
    1679              :     {
    1680              :       /* We can't do anything with other tree codes, so use
    1681              :          VERIFY_CONSTANT to complain and fail.  */
    1682            0 :       VERIFY_CONSTANT (ary);
    1683            0 :       rust_unreachable ();
    1684              :     }
    1685              : 
    1686            8 :   bool found;
    1687            8 :   HOST_WIDE_INT i = 0;
    1688            8 :   if (TREE_CODE (ary) == CONSTRUCTOR)
    1689              :     {
    1690            8 :       HOST_WIDE_INT ix = find_array_ctor_elt (ary, index);
    1691            8 :       found = (ix >= 0);
    1692            8 :       if (found)
    1693            8 :         i = ix;
    1694              :     }
    1695              :   else
    1696              :     {
    1697            0 :       i = tree_to_shwi (index);
    1698            0 :       found = (i < len);
    1699              :     }
    1700              : 
    1701            8 :   if (found)
    1702              :     {
    1703            8 :       tree r;
    1704            8 :       if (TREE_CODE (ary) == CONSTRUCTOR)
    1705            8 :         r = (*CONSTRUCTOR_ELTS (ary))[i].value;
    1706            0 :       else if (TREE_CODE (ary) == VECTOR_CST)
    1707            0 :         r = VECTOR_CST_ELT (ary, i);
    1708              :       else
    1709            0 :         r = extract_string_elt (ary, elem_nchars, i);
    1710              : 
    1711            8 :       if (r)
    1712              :         /* Don't VERIFY_CONSTANT here.  */
    1713              :         return r;
    1714              : 
    1715              :       /* Otherwise the element doesn't have a value yet.  */
    1716              :     }
    1717              : 
    1718              :   /* Not found.  */
    1719              : 
    1720            0 :   if (TREE_CODE (ary) == CONSTRUCTOR && CONSTRUCTOR_NO_CLEARING (ary))
    1721              :     {
    1722              :       /* 'ary' is part of the aggregate initializer we're currently
    1723              :          building; if there's no initializer for this element yet,
    1724              :          that's an error.  */
    1725            0 :       if (!ctx->quiet)
    1726            0 :         error ("accessing uninitialized array element");
    1727            0 :       *non_constant_p = true;
    1728            0 :       return t;
    1729              :     }
    1730              : 
    1731              :   /* If it's within the array bounds but doesn't have an explicit
    1732              :      initializer, it's initialized from {}.  But use build_value_init
    1733              :      directly for non-aggregates to avoid creating a garbage CONSTRUCTOR.  */
    1734            0 :   tree val = NULL_TREE;
    1735            0 :   sorry ("array size expression is not supported yet");
    1736              : 
    1737            0 :   constexpr_ctx new_ctx;
    1738            0 :   if (is_really_empty_class (elem_type, /*ignore_vptr*/ false))
    1739            0 :     return build_constructor (elem_type, NULL);
    1740              :   // else if (CP_AGGREGATE_TYPE_P (elem_type))
    1741              :   // {
    1742              :   //   tree empty_ctor = build_constructor (init_list_type_node, NULL);
    1743              :   //    //val = digest_init (elem_type, empty_ctor, tf_warning_or_error);
    1744              :   //  }
    1745              :   // else
    1746              :   //  val = build_value_init (elem_type, tf_warning_or_error);
    1747              : 
    1748            0 :   if (!SCALAR_TYPE_P (elem_type))
    1749              :     {
    1750            0 :       new_ctx = *ctx;
    1751            0 :       if (ctx->object)
    1752              :         /* If there was no object, don't add one: it could confuse us
    1753              :            into thinking we're modifying a const object.  */
    1754            0 :         new_ctx.object = t;
    1755            0 :       new_ctx.ctor = build_constructor (elem_type, NULL);
    1756            0 :       ctx = &new_ctx;
    1757              :     }
    1758            0 :   t = eval_constant_expression (ctx, val, lval, non_constant_p, overflow_p,
    1759              :                                 jump_target);
    1760            0 :   if (!SCALAR_TYPE_P (elem_type) && t != ctx->ctor)
    1761            0 :     free_constructor (ctx->ctor);
    1762              :   return t;
    1763              : }
    1764              : 
    1765              : // forked from gcc/cp/constexpr.cc cxx_eval_component_reference
    1766              : 
    1767              : /* Subroutine of cxx_eval_constant_expression.
    1768              :    Attempt to reduce a field access of a value of class type.  */
    1769              : 
    1770              : static tree
    1771           11 : eval_component_reference (const constexpr_ctx *ctx, tree t, bool lval,
    1772              :                           bool *non_constant_p, bool *overflow_p,
    1773              :                           tree *jump_target)
    1774              : {
    1775           11 :   unsigned HOST_WIDE_INT i;
    1776           11 :   tree field;
    1777           11 :   tree value;
    1778           11 :   tree part = TREE_OPERAND (t, 1);
    1779           11 :   tree orig_whole = TREE_OPERAND (t, 0);
    1780           11 :   tree whole = eval_constant_expression (ctx, orig_whole, lval, non_constant_p,
    1781              :                                          overflow_p, jump_target);
    1782           11 :   if (INDIRECT_REF_P (whole) && integer_zerop (TREE_OPERAND (whole, 0)))
    1783              :     {
    1784            0 :       if (!ctx->quiet)
    1785            0 :         error ("dereferencing a null pointer in %qE", orig_whole);
    1786            0 :       *non_constant_p = true;
    1787            0 :       return t;
    1788              :     }
    1789              : 
    1790           11 :   if (whole == orig_whole)
    1791              :     return t;
    1792           11 :   if (lval)
    1793            0 :     return fold_build3 (COMPONENT_REF, TREE_TYPE (t), whole, part, NULL_TREE);
    1794              :   /* Don't VERIFY_CONSTANT here; we only want to check that we got a
    1795              :      CONSTRUCTOR.  */
    1796           11 :   if (!*non_constant_p && TREE_CODE (whole) != CONSTRUCTOR)
    1797              :     {
    1798            0 :       if (!ctx->quiet)
    1799            0 :         error ("%qE is not a constant expression", orig_whole);
    1800            0 :       *non_constant_p = true;
    1801              :     }
    1802           11 :   if (DECL_MUTABLE_P (part))
    1803              :     {
    1804            0 :       if (!ctx->quiet)
    1805            0 :         error ("mutable %qD is not usable in a constant expression", part);
    1806            0 :       *non_constant_p = true;
    1807              :     }
    1808           11 :   if (*non_constant_p)
    1809              :     return t;
    1810           11 :   bool pmf = TYPE_PTRMEMFUNC_P (TREE_TYPE (whole));
    1811           12 :   FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (whole), i, field, value)
    1812              :     {
    1813              :       /* Use name match for PMF fields, as a variant will have a
    1814              :          different FIELD_DECL with a different type.  */
    1815           12 :       if (pmf ? DECL_NAME (field) == DECL_NAME (part) : field == part)
    1816              :         {
    1817           11 :           if (value)
    1818              :             {
    1819           11 :               STRIP_ANY_LOCATION_WRAPPER (value);
    1820           11 :               return value;
    1821              :             }
    1822              :           else
    1823              :             /* We're in the middle of initializing it.  */
    1824              :             break;
    1825              :         }
    1826              :     }
    1827            0 :   if (TREE_CODE (TREE_TYPE (whole)) == UNION_TYPE
    1828            0 :       && CONSTRUCTOR_NELTS (whole) > 0)
    1829              :     {
    1830              :       /* DR 1188 says we don't have to deal with this.  */
    1831            0 :       if (!ctx->quiet)
    1832              :         {
    1833            0 :           constructor_elt *cep = CONSTRUCTOR_ELT (whole, 0);
    1834            0 :           if (cep->value == NULL_TREE)
    1835            0 :             error ("accessing uninitialized member %qD", part);
    1836              :           else
    1837            0 :             error ("accessing %qD member instead of initialized %qD member in "
    1838              :                    "constant expression",
    1839              :                    part, cep->index);
    1840              :         }
    1841            0 :       *non_constant_p = true;
    1842            0 :       return t;
    1843              :     }
    1844              : 
    1845              :   /* We only create a CONSTRUCTOR for a subobject when we modify it, so empty
    1846              :      classes never get represented; throw together a value now.  */
    1847            0 :   if (is_really_empty_class (TREE_TYPE (t), /*ignore_vptr*/ false))
    1848            0 :     return build_constructor (TREE_TYPE (t), NULL);
    1849              : 
    1850            0 :   gcc_assert (DECL_CONTEXT (part) == TYPE_MAIN_VARIANT (TREE_TYPE (whole)));
    1851              : 
    1852            0 :   if (CONSTRUCTOR_NO_CLEARING (whole))
    1853              :     {
    1854              :       /* 'whole' is part of the aggregate initializer we're currently
    1855              :          building; if there's no initializer for this member yet, that's an
    1856              :          error.  */
    1857            0 :       if (!ctx->quiet)
    1858            0 :         error ("accessing uninitialized member %qD", part);
    1859            0 :       *non_constant_p = true;
    1860            0 :       return t;
    1861              :     }
    1862              : 
    1863            0 :   value = NULL_TREE;
    1864            0 :   sorry ("constant folding not supported for this tree code");
    1865              :   /* If there's no explicit init for this field, it's value-initialized.  */
    1866              :   // Faisal: commenting this out as not sure if we need this but we need to come
    1867              :   // back to handle this to assign suitable value to value before sending it in
    1868              :   // eval_constant_expression below
    1869              :   // value = build_value_init (TREE_TYPE (t), tf_warning_or_error);
    1870            0 :   return eval_constant_expression (ctx, value, lval, non_constant_p, overflow_p,
    1871            0 :                                    jump_target);
    1872              : }
    1873              : 
    1874              : /* Subroutine of cxx_eval_statement_list.  Determine whether the statement
    1875              :    STMT matches *jump_target.  If we're looking for a case label and we see
    1876              :    the default label, note it in ctx->css_state.  */
    1877              : 
    1878              : static bool
    1879            2 : label_matches (const constexpr_ctx *ctx, tree *jump_target, tree stmt)
    1880              : {
    1881            2 :   switch (TREE_CODE (*jump_target))
    1882              :     {
    1883            2 :     case LABEL_DECL:
    1884            2 :       if (TREE_CODE (stmt) == LABEL_EXPR
    1885            2 :           && LABEL_EXPR_LABEL (stmt) == *jump_target)
    1886            2 :         return true;
    1887              :       break;
    1888              : 
    1889            0 :     case INTEGER_CST:
    1890            0 :       if (TREE_CODE (stmt) == CASE_LABEL_EXPR)
    1891              :         {
    1892            0 :           gcc_assert (ctx->css_state != NULL);
    1893            0 :           if (!CASE_LOW (stmt))
    1894              :             {
    1895              :               /* default: should appear just once in a SWITCH_EXPR
    1896              :                  body (excluding nested SWITCH_EXPR).  */
    1897            0 :               gcc_assert (*ctx->css_state != css_default_seen);
    1898              :               /* When evaluating SWITCH_EXPR body for the second time,
    1899              :                  return true for the default: label.  */
    1900            0 :               if (*ctx->css_state == css_default_processing)
    1901              :                 return true;
    1902            0 :               *ctx->css_state = css_default_seen;
    1903              :             }
    1904            0 :           else if (CASE_HIGH (stmt))
    1905              :             {
    1906            0 :               if (tree_int_cst_le (CASE_LOW (stmt), *jump_target)
    1907            0 :                   && tree_int_cst_le (*jump_target, CASE_HIGH (stmt)))
    1908              :                 return true;
    1909              :             }
    1910            0 :           else if (tree_int_cst_equal (*jump_target, CASE_LOW (stmt)))
    1911              :             return true;
    1912              :         }
    1913              :       break;
    1914              : 
    1915              :     case BREAK_STMT:
    1916              :     case CONTINUE_STMT:
    1917              :       /* These two are handled directly in cxx_eval_loop_expr by testing
    1918              :          breaks (jump_target) or continues (jump_target).  */
    1919              :       break;
    1920              : 
    1921            0 :     default:
    1922            0 :       rust_unreachable ();
    1923              :     }
    1924              :   return false;
    1925              : }
    1926              : 
    1927              : static tree
    1928      1858390 : eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
    1929              :                           bool *non_constant_p, bool *overflow_p,
    1930              :                           tree *jump_target)
    1931              : {
    1932      1858390 :   if (t == NULL_TREE)
    1933              :     return NULL_TREE;
    1934              : 
    1935      1596243 :   if (jump_target && *jump_target)
    1936              :     {
    1937              :       /* If we are jumping, ignore all statements/expressions except those
    1938              :          that could have LABEL_EXPR or CASE_LABEL_EXPR in their bodies.  */
    1939            7 :       switch (TREE_CODE (t))
    1940              :         {
    1941              :         case BIND_EXPR:
    1942              :         case STATEMENT_LIST:
    1943              :         case LOOP_EXPR:
    1944              :         case COND_EXPR:
    1945              :         case IF_STMT:
    1946              :         case DO_STMT:
    1947              :         case WHILE_STMT:
    1948              :         case FOR_STMT:
    1949              :           break;
    1950            2 :         case LABEL_EXPR:
    1951            2 :         case CASE_LABEL_EXPR:
    1952            2 :           if (label_matches (ctx, jump_target, t))
    1953              :             /* Found it.  */
    1954            2 :             *jump_target = NULL_TREE;
    1955              :           return NULL_TREE;
    1956              :         default:
    1957              :           return NULL_TREE;
    1958              :         }
    1959              :     }
    1960      1596239 :   if (error_operand_p (t))
    1961              :     {
    1962            4 :       *non_constant_p = true;
    1963            4 :       return t;
    1964              :     }
    1965              : 
    1966      1596235 :   location_t loc = EXPR_LOCATION (t);
    1967              : 
    1968      1596235 :   if (CONSTANT_CLASS_P (t))
    1969              :     {
    1970       266427 :       if (TREE_OVERFLOW (t))
    1971              :         {
    1972            0 :           error_at (loc, "overflow in constant expression");
    1973            0 :           return t;
    1974              :         }
    1975              : 
    1976              :       return t;
    1977              :     }
    1978              : 
    1979              :   // Avoid excessively long constexpr evaluations
    1980      1329808 :   if (++ctx->global->constexpr_ops_count >= constexpr_ops_limit)
    1981              :     {
    1982            0 :       rust_error_at (
    1983              :         loc,
    1984              :         "%<constexpr%> evaluation operation count exceeds limit of "
    1985              :         "%wd (use %<-fconstexpr-ops-limit=%> to increase the limit)",
    1986              :         constexpr_ops_limit);
    1987              : 
    1988            0 :       return t;
    1989              :     }
    1990              : 
    1991      1329808 :   constexpr_ctx new_ctx;
    1992      1329808 :   tree r = t;
    1993      1329808 :   tree_code tcode = TREE_CODE (t);
    1994      1329808 :   switch (tcode)
    1995              :     {
    1996          263 :     case VAR_DECL:
    1997          263 :       if (DECL_HAS_VALUE_EXPR_P (t))
    1998              :         {
    1999            0 :           r = DECL_VALUE_EXPR (t);
    2000            0 :           return eval_constant_expression (ctx, r, lval, non_constant_p,
    2001            0 :                                            overflow_p, jump_target);
    2002              :         }
    2003              :     /* fall through */
    2004         1725 :     case CONST_DECL:
    2005              :       /* We used to not check lval for CONST_DECL, but darwin.cc uses
    2006              :          CONST_DECL for aggregate constants.  */
    2007         1725 :       if (lval)
    2008              :         return t;
    2009         1613 :       else if (t == ctx->object)
    2010            0 :         return ctx->ctor;
    2011         1613 :       if (VAR_P (t))
    2012              :         {
    2013          151 :           if (tree v = ctx->global->get_value (t))
    2014              :             {
    2015          149 :               r = v;
    2016          149 :               break;
    2017              :             }
    2018              :         }
    2019         1464 :       if (COMPLETE_TYPE_P (TREE_TYPE (t))
    2020         1464 :           && is_really_empty_class (TREE_TYPE (t), /*ignore_vptr*/ false))
    2021              :         {
    2022              :           /* If the class is empty, we aren't actually loading anything.  */
    2023            0 :           r = build_constructor (TREE_TYPE (t), NULL);
    2024            0 :           TREE_CONSTANT (r) = true;
    2025              :         }
    2026         1464 :       else if (ctx->strict)
    2027         1464 :         r = decl_really_constant_value (t, /*unshare_p=*/false);
    2028              :       else
    2029            0 :         r = decl_constant_value (t, /*unshare_p=*/false);
    2030         1464 :       if (TREE_CODE (r) == TARGET_EXPR
    2031         1464 :           && TREE_CODE (TARGET_EXPR_INITIAL (r)) == CONSTRUCTOR)
    2032            0 :         r = TARGET_EXPR_INITIAL (r);
    2033         1464 :       if (DECL_P (r) && !(VAR_P (t) && TYPE_REF_P (TREE_TYPE (t))))
    2034              :         {
    2035            2 :           if (!ctx->quiet)
    2036            2 :             non_const_var_error (loc, r);
    2037            2 :           *non_constant_p = true;
    2038              :         }
    2039              :       break;
    2040              : 
    2041           59 :     case PARM_DECL:
    2042           59 :       if (lval && !TYPE_REF_P (TREE_TYPE (t)))
    2043              :         /* glvalue use.  */;
    2044           48 :       else if (tree *p = ctx->global->values.get (r))
    2045           48 :         r = *p;
    2046            0 :       else if (lval)
    2047              :         /* Defer in case this is only used for its type.  */;
    2048            0 :       else if (COMPLETE_TYPE_P (TREE_TYPE (t))
    2049            0 :                && is_really_empty_class (TREE_TYPE (t), /*ignore_vptr*/ false))
    2050              :         {
    2051              :           /* If the class is empty, we aren't actually loading anything.  */
    2052            0 :           r = build_constructor (TREE_TYPE (t), NULL);
    2053            0 :           TREE_CONSTANT (r) = true;
    2054              :         }
    2055              :       else
    2056              :         {
    2057            0 :           if (!ctx->quiet)
    2058            0 :             error ("%qE is not a constant expression", t);
    2059            0 :           *non_constant_p = true;
    2060              :         }
    2061              :       break;
    2062              : 
    2063          349 :     case POINTER_PLUS_EXPR:
    2064          349 :     case POINTER_DIFF_EXPR:
    2065          349 :     case PLUS_EXPR:
    2066          349 :     case MINUS_EXPR:
    2067          349 :     case MULT_EXPR:
    2068          349 :     case TRUNC_DIV_EXPR:
    2069          349 :     case CEIL_DIV_EXPR:
    2070          349 :     case FLOOR_DIV_EXPR:
    2071          349 :     case ROUND_DIV_EXPR:
    2072          349 :     case TRUNC_MOD_EXPR:
    2073          349 :     case CEIL_MOD_EXPR:
    2074          349 :     case ROUND_MOD_EXPR:
    2075          349 :     case RDIV_EXPR:
    2076          349 :     case EXACT_DIV_EXPR:
    2077          349 :     case MIN_EXPR:
    2078          349 :     case MAX_EXPR:
    2079          349 :     case LSHIFT_EXPR:
    2080          349 :     case RSHIFT_EXPR:
    2081          349 :     case LROTATE_EXPR:
    2082          349 :     case RROTATE_EXPR:
    2083          349 :     case BIT_IOR_EXPR:
    2084          349 :     case BIT_XOR_EXPR:
    2085          349 :     case BIT_AND_EXPR:
    2086          349 :     case TRUTH_XOR_EXPR:
    2087          349 :     case LT_EXPR:
    2088          349 :     case LE_EXPR:
    2089          349 :     case GT_EXPR:
    2090          349 :     case GE_EXPR:
    2091          349 :     case EQ_EXPR:
    2092          349 :     case NE_EXPR:
    2093          349 :     case SPACESHIP_EXPR:
    2094          349 :     case UNORDERED_EXPR:
    2095          349 :     case ORDERED_EXPR:
    2096          349 :     case UNLT_EXPR:
    2097          349 :     case UNLE_EXPR:
    2098          349 :     case UNGT_EXPR:
    2099          349 :     case UNGE_EXPR:
    2100          349 :     case UNEQ_EXPR:
    2101          349 :     case LTGT_EXPR:
    2102          349 :     case RANGE_EXPR:
    2103          349 :     case COMPLEX_EXPR:
    2104          349 :       r = eval_binary_expression (ctx, t, lval, non_constant_p, overflow_p,
    2105              :                                   jump_target);
    2106          349 :       break;
    2107              : 
    2108              :       /* fold can introduce non-IF versions of these; still treat them as
    2109              :          short-circuiting.  */
    2110            0 :     case TRUTH_AND_EXPR:
    2111            0 :     case TRUTH_ANDIF_EXPR:
    2112            0 :       r = eval_logical_expression (ctx, t, boolean_false_node,
    2113              :                                    boolean_true_node, lval, non_constant_p,
    2114              :                                    overflow_p, jump_target);
    2115            0 :       break;
    2116              : 
    2117            0 :     case TRUTH_OR_EXPR:
    2118            0 :     case TRUTH_ORIF_EXPR:
    2119            0 :       r = eval_logical_expression (ctx, t, boolean_true_node,
    2120              :                                    boolean_false_node, lval, non_constant_p,
    2121              :                                    overflow_p, jump_target);
    2122            0 :       break;
    2123              : 
    2124            0 :     case TARGET_EXPR:
    2125            0 :       {
    2126            0 :         tree type = TREE_TYPE (t);
    2127              : 
    2128            0 :         if (!literal_type_p (type))
    2129              :           {
    2130            0 :             if (!ctx->quiet)
    2131              :               {
    2132            0 :                 auto_diagnostic_group d;
    2133            0 :                 error ("temporary of non-literal type %qT in a "
    2134              :                        "constant expression",
    2135              :                        type);
    2136            0 :                 explain_non_literal_class (type);
    2137            0 :               }
    2138            0 :             *non_constant_p = true;
    2139            0 :             break;
    2140              :           }
    2141            0 :         gcc_checking_assert (!TARGET_EXPR_DIRECT_INIT_P (t));
    2142              :         /* Avoid evaluating a TARGET_EXPR more than once.  */
    2143            0 :         tree slot = TARGET_EXPR_SLOT (t);
    2144            0 :         if (tree *p = ctx->global->values.get (slot))
    2145              :           {
    2146            0 :             if (lval)
    2147            0 :               return slot;
    2148            0 :             r = *p;
    2149            0 :             break;
    2150              :           }
    2151            0 :         if ((AGGREGATE_TYPE_P (type) || VECTOR_TYPE_P (type)))
    2152              :           {
    2153              :             /* We're being expanded without an explicit target, so start
    2154              :                initializing a new object; expansion with an explicit target
    2155              :                strips the TARGET_EXPR before we get here.  */
    2156            0 :             new_ctx = *ctx;
    2157              :             /* Link CTX to NEW_CTX so that lookup_placeholder can resolve
    2158              :                any PLACEHOLDER_EXPR within the initializer that refers to the
    2159              :                former object under construction.  */
    2160            0 :             new_ctx.parent = ctx;
    2161            0 :             new_ctx.ctor = build_constructor (type, NULL);
    2162            0 :             CONSTRUCTOR_NO_CLEARING (new_ctx.ctor) = true;
    2163            0 :             new_ctx.object = slot;
    2164            0 :             ctx->global->values.put (new_ctx.object, new_ctx.ctor);
    2165            0 :             ctx = &new_ctx;
    2166              :           }
    2167              :         /* Pass false for 'lval' because this indicates
    2168              :            initialization of a temporary.  */
    2169            0 :         r = eval_constant_expression (ctx, TREE_OPERAND (t, 1), false,
    2170              :                                       non_constant_p, overflow_p, jump_target);
    2171            0 :         if (*non_constant_p)
    2172              :           break;
    2173              :         /* Adjust the type of the result to the type of the temporary.  */
    2174            0 :         r = adjust_temp_type (type, r);
    2175            0 :         if (TARGET_EXPR_CLEANUP (t) && !CLEANUP_EH_ONLY (t))
    2176            0 :           ctx->global->cleanups->safe_push (TARGET_EXPR_CLEANUP (t));
    2177            0 :         r = unshare_constructor (r);
    2178            0 :         ctx->global->values.put (slot, r);
    2179            0 :         if (ctx->save_exprs)
    2180            0 :           ctx->save_exprs->safe_push (slot);
    2181            0 :         if (lval)
    2182              :           return slot;
    2183              :       }
    2184            0 :       break;
    2185              : 
    2186         2405 :     case CALL_EXPR:
    2187         2405 :       r = eval_call_expression (ctx, t, lval, non_constant_p, overflow_p,
    2188              :                                 jump_target);
    2189         2405 :       break;
    2190              : 
    2191         2395 :     case RETURN_EXPR:
    2192         2395 :       if (TREE_OPERAND (t, 0) != NULL_TREE)
    2193         2395 :         r = eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval,
    2194              :                                       non_constant_p, overflow_p, jump_target);
    2195              :       /* FALLTHRU */
    2196         2395 :     case BREAK_STMT:
    2197         2395 :     case CONTINUE_STMT:
    2198         2395 :       if (jump_target)
    2199         2395 :         *jump_target = t;
    2200              :       else
    2201              :         {
    2202              :           /* Can happen with ({ return true; }) && false; passed to
    2203              :              maybe_constant_value.  There is nothing to jump over in this
    2204              :              case, and the bug will be diagnosed later.  */
    2205            0 :           gcc_assert (ctx->quiet);
    2206            0 :           *non_constant_p = true;
    2207              :         }
    2208              :       break;
    2209              : 
    2210         2034 :     case DECL_EXPR:
    2211         2034 :       {
    2212         2034 :         r = DECL_EXPR_DECL (t);
    2213              : 
    2214         2034 :         if (AGGREGATE_TYPE_P (TREE_TYPE (r)) || VECTOR_TYPE_P (TREE_TYPE (r)))
    2215              :           {
    2216           83 :             new_ctx = *ctx;
    2217           83 :             new_ctx.object = r;
    2218           83 :             new_ctx.ctor = build_constructor (TREE_TYPE (r), NULL);
    2219           83 :             CONSTRUCTOR_NO_CLEARING (new_ctx.ctor) = true;
    2220           83 :             ctx->global->values.put (r, new_ctx.ctor);
    2221           83 :             ctx = &new_ctx;
    2222              :           }
    2223              : 
    2224         2034 :         if (tree init = DECL_INITIAL (r))
    2225              :           {
    2226           29 :             init = eval_constant_expression (ctx, init, false, non_constant_p,
    2227              :                                              overflow_p, jump_target);
    2228              :             /* Don't share a CONSTRUCTOR that might be changed.  */
    2229           29 :             init = unshare_constructor (init);
    2230              :             /* Remember that a constant object's constructor has already
    2231              :                run.  */
    2232           29 :             if (CLASS_TYPE_P (TREE_TYPE (r)) && RS_TYPE_CONST_P (TREE_TYPE (r)))
    2233            0 :               TREE_READONLY (init) = true;
    2234           29 :             ctx->global->values.put (r, init);
    2235              :           }
    2236         2005 :         else if (ctx == &new_ctx)
    2237              :           /* We gave it a CONSTRUCTOR above.  */;
    2238              :         else
    2239         1924 :           ctx->global->values.put (r, NULL_TREE);
    2240              :       }
    2241         2034 :       break;
    2242              : 
    2243              :     /* These differ from cxx_eval_unary_expression in that this doesn't
    2244              :          check for a constant operand or result; an address can be
    2245              :          constant without its operand being, and vice versa.  */
    2246            3 :     case MEM_REF:
    2247            3 :     case INDIRECT_REF:
    2248            3 :       r = rs_eval_indirect_ref (ctx, t, lval, non_constant_p, overflow_p,
    2249              :                                 jump_target);
    2250            3 :       break;
    2251              : 
    2252            0 :     case VEC_PERM_EXPR:
    2253            0 :       r = cxx_eval_trinary_expression (ctx, t, lval, non_constant_p, overflow_p,
    2254              :                                        jump_target);
    2255            0 :       break;
    2256              : 
    2257            0 :     case PAREN_EXPR:
    2258            0 :       gcc_assert (!REF_PARENTHESIZED_P (t));
    2259              :       /* A PAREN_EXPR resulting from __builtin_assoc_barrier has no effect in
    2260              :          constant expressions since it's unaffected by -fassociative-math.  */
    2261            0 :       r = eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval,
    2262              :                                     non_constant_p, overflow_p, jump_target);
    2263            0 :       break;
    2264              : 
    2265         2516 :     case MODIFY_EXPR:
    2266         2516 :       r = eval_store_expression (ctx, t, false, non_constant_p, overflow_p,
    2267              :                                  jump_target);
    2268         2516 :       break;
    2269              : 
    2270       264641 :     case STATEMENT_LIST:
    2271       264641 :       new_ctx = *ctx;
    2272       264641 :       new_ctx.ctor = new_ctx.object = NULL_TREE;
    2273       264641 :       return eval_statement_list (&new_ctx, t, non_constant_p, overflow_p,
    2274       264641 :                                   jump_target);
    2275              : 
    2276       526787 :     case BIND_EXPR:
    2277       526787 :       return eval_constant_expression (ctx, BIND_EXPR_BODY (t), lval,
    2278       526787 :                                        non_constant_p, overflow_p, jump_target);
    2279              : 
    2280            0 :     case OBJ_TYPE_REF:
    2281              :       /* Virtual function lookup.  We don't need to do anything fancy.  */
    2282            0 :       return eval_constant_expression (ctx, OBJ_TYPE_REF_EXPR (t), lval,
    2283            0 :                                        non_constant_p, overflow_p, jump_target);
    2284              : 
    2285       262160 :     case EXIT_EXPR:
    2286       262160 :       {
    2287       262160 :         tree cond = TREE_OPERAND (t, 0);
    2288       262160 :         cond
    2289       262160 :           = eval_constant_expression (ctx, cond, /*lval*/ false, non_constant_p,
    2290              :                                       overflow_p, jump_target);
    2291       262160 :         VERIFY_CONSTANT (cond);
    2292       262160 :         if (integer_nonzerop (cond))
    2293            4 :           *jump_target = t;
    2294              :       }
    2295              :       break;
    2296              : 
    2297         2380 :     case RESULT_DECL:
    2298         2380 :       if (lval)
    2299              :         return t;
    2300              :       /* We ask for an rvalue for the RESULT_DECL when indirecting
    2301              :          through an invisible reference, or in named return value
    2302              :          optimization.  */
    2303            0 :       if (tree *p = ctx->global->values.get (t))
    2304            0 :         return *p;
    2305              :       else
    2306              :         {
    2307            0 :           if (!ctx->quiet)
    2308            0 :             error ("%qE is not a constant expression", t);
    2309            0 :           *non_constant_p = true;
    2310              :         }
    2311            0 :       break;
    2312              : 
    2313            0 :     case SAVE_EXPR:
    2314              :       /* Avoid evaluating a SAVE_EXPR more than once.  */
    2315            0 :       if (tree *p = ctx->global->values.get (t))
    2316            0 :         r = *p;
    2317              :       else
    2318              :         {
    2319            0 :           r = eval_constant_expression (ctx, TREE_OPERAND (t, 0), false,
    2320              :                                         non_constant_p, overflow_p,
    2321              :                                         jump_target);
    2322            0 :           if (*non_constant_p)
    2323              :             break;
    2324            0 :           ctx->global->values.put (t, r);
    2325            0 :           if (ctx->save_exprs)
    2326            0 :             ctx->save_exprs->safe_push (t);
    2327              :         }
    2328              :       break;
    2329              : 
    2330            9 :     case ADDR_EXPR:
    2331            9 :       {
    2332            9 :         tree oldop = TREE_OPERAND (t, 0);
    2333            9 :         tree op = eval_constant_expression (ctx, oldop,
    2334              :                                             /*lval*/ true, non_constant_p,
    2335              :                                             overflow_p, jump_target);
    2336              :         /* Don't VERIFY_CONSTANT here.  */
    2337            9 :         if (*non_constant_p)
    2338              :           return t;
    2339              :         /* This function does more aggressive folding than fold itself.  */
    2340            8 :         r = build_fold_addr_expr_with_type (op, TREE_TYPE (t));
    2341            8 :         if (TREE_CODE (r) == ADDR_EXPR && TREE_OPERAND (r, 0) == oldop)
    2342              :           {
    2343            8 :             ggc_free (r);
    2344            8 :             return t;
    2345              :           }
    2346              :         break;
    2347              :       }
    2348              : 
    2349            0 :     case COMPOUND_EXPR:
    2350            0 :       {
    2351              :         /* check_return_expr sometimes wraps a TARGET_EXPR in a
    2352              :            COMPOUND_EXPR; don't get confused.  Also handle EMPTY_CLASS_EXPR
    2353              :            introduced by build_call_a.  */
    2354            0 :         tree op0 = TREE_OPERAND (t, 0);
    2355            0 :         tree op1 = TREE_OPERAND (t, 1);
    2356            0 :         STRIP_NOPS (op1);
    2357            0 :         if ((TREE_CODE (op0) == TARGET_EXPR && op1 == TARGET_EXPR_SLOT (op0))
    2358            0 :             || TREE_CODE (op1) == EMPTY_CLASS_EXPR)
    2359            0 :           r = eval_constant_expression (ctx, op0, lval, non_constant_p,
    2360              :                                         overflow_p, jump_target);
    2361              :         else
    2362              :           {
    2363              :             /* Check that the LHS is constant and then discard it.  */
    2364            0 :             eval_constant_expression (ctx, op0, true, non_constant_p,
    2365              :                                       overflow_p, jump_target);
    2366            0 :             if (*non_constant_p)
    2367              :               return t;
    2368            0 :             op1 = TREE_OPERAND (t, 1);
    2369            0 :             r = eval_constant_expression (ctx, op1, lval, non_constant_p,
    2370              :                                           overflow_p, jump_target);
    2371              :           }
    2372              :       }
    2373              :       break;
    2374              : 
    2375            0 :     case REALPART_EXPR:
    2376            0 :     case IMAGPART_EXPR:
    2377            0 :       if (lval)
    2378              :         {
    2379            0 :           r = eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval,
    2380              :                                         non_constant_p, overflow_p,
    2381              :                                         jump_target);
    2382            0 :           if (r == error_mark_node)
    2383              :             ;
    2384            0 :           else if (r == TREE_OPERAND (t, 0))
    2385            0 :             r = t;
    2386              :           else
    2387            0 :             r = fold_build1 (TREE_CODE (t), TREE_TYPE (t), r);
    2388              :           break;
    2389              :         }
    2390              :       /* FALLTHRU */
    2391            7 :     case CONJ_EXPR:
    2392            7 :     case FIX_TRUNC_EXPR:
    2393            7 :     case FLOAT_EXPR:
    2394            7 :     case NEGATE_EXPR:
    2395            7 :     case ABS_EXPR:
    2396            7 :     case ABSU_EXPR:
    2397            7 :     case BIT_NOT_EXPR:
    2398            7 :     case TRUTH_NOT_EXPR:
    2399            7 :     case FIXED_CONVERT_EXPR:
    2400            7 :       r = eval_unary_expression (ctx, t, lval, non_constant_p, overflow_p,
    2401              :                                  jump_target);
    2402            7 :       break;
    2403              : 
    2404            2 :     case GOTO_EXPR:
    2405            2 :       {
    2406            2 :         tree target = TREE_OPERAND (t, 0);
    2407            4 :         if (breaks (&target) || continues (&target) || returns (&target)
    2408            4 :             || (TREE_CODE (target) == LABEL_DECL && DECL_ARTIFICIAL (target)))
    2409              :           {
    2410            2 :             if (jump_target)
    2411            2 :               *jump_target = target;
    2412              :             else
    2413              :               {
    2414            0 :                 gcc_assert (ctx->quiet);
    2415            0 :                 *non_constant_p = true;
    2416              :               }
    2417              :           }
    2418              :         else
    2419              :           {
    2420            0 :             if (!ctx->quiet)
    2421            0 :               error_at (loc, "%<goto%> is not a constant expression");
    2422            0 :             *non_constant_p = true;
    2423              :           }
    2424              :       }
    2425            2 :       break;
    2426              : 
    2427            5 :     case LOOP_EXPR:
    2428            5 :     case WHILE_STMT:
    2429            5 :     case FOR_STMT:
    2430            5 :       eval_loop_expr (ctx, t, non_constant_p, overflow_p, jump_target);
    2431            5 :       break;
    2432              : 
    2433            0 :     case SWITCH_EXPR:
    2434            0 :     case SWITCH_STMT:
    2435            0 :       eval_switch_expr (ctx, t, non_constant_p, overflow_p, jump_target);
    2436            0 :       break;
    2437              : 
    2438            9 :     case ARRAY_REF:
    2439            9 :       r = eval_array_reference (ctx, t, lval, non_constant_p, overflow_p,
    2440              :                                 jump_target);
    2441            9 :       break;
    2442              : 
    2443           11 :     case COMPONENT_REF:
    2444           11 :       if (is_overloaded_fn (t))
    2445              :         {
    2446              :           /* We can only get here in checking mode via
    2447              :              build_non_dependent_expr,  because any expression that
    2448              :              calls or takes the address of the function will have
    2449              :              pulled a FUNCTION_DECL out of the COMPONENT_REF.  */
    2450            0 :           gcc_checking_assert (ctx->quiet || errorcount);
    2451            0 :           *non_constant_p = true;
    2452            0 :           return t;
    2453              :         }
    2454           11 :       r = eval_component_reference (ctx, t, lval, non_constant_p, overflow_p,
    2455              :                                     jump_target);
    2456           11 :       break;
    2457              : 
    2458            0 :     case BIT_FIELD_REF:
    2459            0 :       r = eval_bit_field_ref (ctx, t, lval, non_constant_p, overflow_p,
    2460              :                               jump_target);
    2461            0 :       break;
    2462              : 
    2463           22 :     case COND_EXPR:
    2464           22 :     case IF_STMT: // comes from cp-tree.def
    2465           22 :       if (jump_target && *jump_target)
    2466              :         {
    2467            1 :           tree orig_jump = *jump_target;
    2468            0 :           tree arg = ((TREE_CODE (t) != IF_STMT || TREE_OPERAND (t, 1))
    2469            1 :                         ? TREE_OPERAND (t, 1)
    2470            1 :                         : void_node);
    2471              :           /* When jumping to a label, the label might be either in the
    2472              :              then or else blocks, so process then block first in skipping
    2473              :              mode first, and if we are still in the skipping mode at its end,
    2474              :              process the else block too.  */
    2475            1 :           r = eval_constant_expression (ctx, arg, lval, non_constant_p,
    2476              :                                         overflow_p, jump_target);
    2477              :           /* It's possible that we found the label in the then block.  But
    2478              :              it could have been followed by another jumping statement, e.g.
    2479              :              say we're looking for case 1:
    2480              :               if (cond)
    2481              :                 {
    2482              :                   // skipped statements
    2483              :                   case 1:; // clears up *jump_target
    2484              :                   return 1; // and sets it to a RETURN_EXPR
    2485              :                 }
    2486              :               else { ... }
    2487              :              in which case we need not go looking to the else block.
    2488              :              (goto is not allowed in a constexpr function.)  */
    2489            1 :           if (*jump_target == orig_jump)
    2490              :             {
    2491            1 :               arg = ((TREE_CODE (t) != IF_STMT || TREE_OPERAND (t, 2))
    2492            1 :                        ? TREE_OPERAND (t, 2)
    2493              :                        : void_node);
    2494            1 :               r = eval_constant_expression (ctx, arg, lval, non_constant_p,
    2495              :                                             overflow_p, jump_target);
    2496              :             }
    2497              :           break;
    2498              :         }
    2499           21 :       r = eval_conditional_expression (ctx, t, lval, non_constant_p, overflow_p,
    2500              :                                        jump_target);
    2501           21 :       break;
    2502              : 
    2503            0 :     case VEC_COND_EXPR:
    2504            0 :       r = eval_vector_conditional_expression (ctx, t, non_constant_p,
    2505              :                                               overflow_p, jump_target);
    2506            0 :       break;
    2507              : 
    2508            0 :     case TRY_CATCH_EXPR:
    2509            0 :       if (TREE_OPERAND (t, 0) == NULL_TREE)
    2510              :         {
    2511            0 :           r = void_node;
    2512            0 :           break;
    2513              :         }
    2514            0 :       r = eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval,
    2515              :                                     non_constant_p, overflow_p, jump_target);
    2516            0 :       break;
    2517              : 
    2518            0 :     case CLEANUP_POINT_EXPR:
    2519            0 :       {
    2520            0 :         auto_vec<tree, 2> cleanups;
    2521            0 :         vec<tree> *prev_cleanups = ctx->global->cleanups;
    2522            0 :         ctx->global->cleanups = &cleanups;
    2523            0 :         r = eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval,
    2524              :                                       non_constant_p, overflow_p, jump_target);
    2525            0 :         ctx->global->cleanups = prev_cleanups;
    2526            0 :         unsigned int i;
    2527            0 :         tree cleanup;
    2528              :         /* Evaluate the cleanups.  */
    2529            0 :         FOR_EACH_VEC_ELT_REVERSE (cleanups, i, cleanup)
    2530            0 :           eval_constant_expression (ctx, cleanup, false, non_constant_p,
    2531              :                                     overflow_p, jump_target);
    2532            0 :       }
    2533            0 :       break;
    2534              : 
    2535            0 :     case TRY_FINALLY_EXPR:
    2536            0 :       r = eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval,
    2537              :                                     non_constant_p, overflow_p, jump_target);
    2538            0 :       if (!*non_constant_p)
    2539              :         /* Also evaluate the cleanup.  */
    2540            0 :         eval_constant_expression (ctx, TREE_OPERAND (t, 1), true,
    2541              :                                   non_constant_p, overflow_p, jump_target);
    2542              :       break;
    2543              : 
    2544           77 :     case CONSTRUCTOR:
    2545           77 :       if (TREE_CONSTANT (t) && reduced_constant_expression_p (t))
    2546              :         {
    2547              :           /* Don't re-process a constant CONSTRUCTOR, but do fold it to
    2548              :              VECTOR_CST if applicable.  */
    2549           75 :           verify_constructor_flags (t);
    2550           75 :           if (TREE_CONSTANT (t))
    2551           75 :             return fold (t);
    2552              :         }
    2553            2 :       r = eval_bare_aggregate (ctx, t, lval, non_constant_p, overflow_p,
    2554              :                                jump_target);
    2555            2 :       break;
    2556              : 
    2557              :       /* FALLTHROUGH.  */
    2558           49 :     case NOP_EXPR:
    2559           49 :     case CONVERT_EXPR:
    2560           49 :     case VIEW_CONVERT_EXPR:
    2561           49 :       {
    2562           49 :         tree oldop = TREE_OPERAND (t, 0);
    2563              : 
    2564           49 :         tree op = eval_constant_expression (ctx, oldop, lval, non_constant_p,
    2565              :                                             overflow_p, jump_target);
    2566           49 :         if (*non_constant_p)
    2567              :           return t;
    2568           48 :         tree type = TREE_TYPE (t);
    2569              : 
    2570           48 :         if (VOID_TYPE_P (type))
    2571            0 :           return void_node;
    2572              : 
    2573            0 :         if (TREE_CODE (t) == CONVERT_EXPR && ARITHMETIC_TYPE_P (type)
    2574           48 :             && INDIRECT_TYPE_P (TREE_TYPE (op)) && ctx->manifestly_const_eval)
    2575              :           {
    2576            0 :             if (!ctx->quiet)
    2577            0 :               error_at (loc,
    2578              :                         "conversion from pointer type %qT to arithmetic type "
    2579              :                         "%qT in a constant expression",
    2580            0 :                         TREE_TYPE (op), type);
    2581            0 :             *non_constant_p = true;
    2582            0 :             return t;
    2583              :           }
    2584              : 
    2585            4 :         if (TYPE_PTROB_P (type) && TYPE_PTR_P (TREE_TYPE (op))
    2586           49 :             && VOID_TYPE_P (TREE_TYPE (TREE_TYPE (op))))
    2587              :           {
    2588              :             /* Likewise, don't error when casting from void* when OP is
    2589              :                &heap uninit and similar.  */
    2590            0 :             tree sop = tree_strip_nop_conversions (op);
    2591            0 :             if (TREE_CODE (sop) == ADDR_EXPR && VAR_P (TREE_OPERAND (sop, 0))
    2592            0 :                 && DECL_ARTIFICIAL (TREE_OPERAND (sop, 0)))
    2593              :               /* OK */;
    2594              :             else
    2595              :               {
    2596            0 :                 if (!ctx->quiet)
    2597            0 :                   error_at (loc, "cast from %qT is not allowed",
    2598            0 :                             TREE_TYPE (op));
    2599            0 :                 *non_constant_p = true;
    2600            0 :                 return t;
    2601              :               }
    2602              :           }
    2603              : 
    2604           48 :         if (INDIRECT_TYPE_P (type) && TREE_CODE (op) == INTEGER_CST)
    2605              :           {
    2606            0 :             if (integer_zerop (op))
    2607              :               {
    2608            0 :                 if (TYPE_REF_P (type))
    2609              :                   {
    2610            0 :                     if (!ctx->quiet)
    2611            0 :                       error_at (loc, "dereferencing a null pointer");
    2612            0 :                     *non_constant_p = true;
    2613            0 :                     return t;
    2614              :                   }
    2615              :               }
    2616              :             else
    2617              :               {
    2618              :                 /* This detects for example:
    2619              :                      reinterpret_cast<void*>(sizeof 0)
    2620              :                 */
    2621            0 :                 if (!ctx->quiet)
    2622            0 :                   error_at (loc,
    2623              :                             "%<reinterpret_cast<%T>(%E)%> is not "
    2624              :                             "a constant expression",
    2625              :                             type, op);
    2626            0 :                 *non_constant_p = true;
    2627            0 :                 return t;
    2628              :               }
    2629              :           }
    2630              : 
    2631            4 :         if (INDIRECT_TYPE_P (type) && TREE_CODE (op) == NOP_EXPR
    2632            1 :             && TREE_TYPE (op) == ptr_type_node
    2633            0 :             && TREE_CODE (TREE_OPERAND (op, 0)) == ADDR_EXPR
    2634            0 :             && VAR_P (TREE_OPERAND (TREE_OPERAND (op, 0), 0))
    2635           48 :             && (DECL_NAME (TREE_OPERAND (TREE_OPERAND (op, 0), 0))
    2636            0 :                   == heap_uninit_identifier
    2637            0 :                 || DECL_NAME (TREE_OPERAND (TREE_OPERAND (op, 0), 0))
    2638            0 :                      == heap_vec_uninit_identifier))
    2639              :           {
    2640            0 :             tree var = TREE_OPERAND (TREE_OPERAND (op, 0), 0);
    2641            0 :             tree var_size = TYPE_SIZE_UNIT (TREE_TYPE (var));
    2642            0 :             tree elt_type = TREE_TYPE (type);
    2643            0 :             tree cookie_size = NULL_TREE;
    2644            0 :             if (TREE_CODE (elt_type) == RECORD_TYPE
    2645            0 :                 && TYPE_NAME (elt_type) == heap_identifier)
    2646              :               {
    2647            0 :                 tree fld1 = TYPE_FIELDS (elt_type);
    2648            0 :                 tree fld2 = DECL_CHAIN (fld1);
    2649            0 :                 elt_type = TREE_TYPE (TREE_TYPE (fld2));
    2650            0 :                 cookie_size = TYPE_SIZE_UNIT (TREE_TYPE (fld1));
    2651              :               }
    2652            0 :             DECL_NAME (var) = (DECL_NAME (var) == heap_uninit_identifier
    2653            0 :                                  ? heap_identifier
    2654              :                                  : heap_vec_identifier);
    2655            0 :             TREE_TYPE (var)
    2656            0 :               = build_new_constexpr_heap_type (elt_type, cookie_size, var_size);
    2657            0 :             TREE_TYPE (TREE_OPERAND (op, 0))
    2658            0 :               = build_pointer_type (TREE_TYPE (var));
    2659              :           }
    2660              : 
    2661           48 :         if (op == oldop)
    2662              :           /* We didn't fold at the top so we could check for ptr-int
    2663              :              conversion.  */
    2664            3 :           return fold (t);
    2665              : 
    2666           45 :         tree sop;
    2667              : 
    2668              :         /* Handle an array's bounds having been deduced after we built
    2669              :            the wrapping expression.  */
    2670           45 :         if (same_type_ignoring_tlq_and_bounds_p (type, TREE_TYPE (op)))
    2671           44 :           r = op;
    2672            1 :         else if (sop = tree_strip_nop_conversions (op),
    2673              :                  sop != op
    2674            1 :                    && (same_type_ignoring_tlq_and_bounds_p (type,
    2675            0 :                                                             TREE_TYPE (sop))))
    2676            0 :           r = sop;
    2677              :         else
    2678            1 :           r = fold_build1 (tcode, type, op);
    2679              : 
    2680              :         /* Conversion of an out-of-range value has implementation-defined
    2681              :            behavior; the language considers it different from arithmetic
    2682              :            overflow, which is undefined.  */
    2683           45 :         if (TREE_OVERFLOW_P (r) && !TREE_OVERFLOW_P (op))
    2684            0 :           TREE_OVERFLOW (r) = false;
    2685              :       }
    2686              :       break;
    2687              : 
    2688            0 :     case PLACEHOLDER_EXPR:
    2689              :       /* Use of the value or address of the current object.  */
    2690            0 :       if (tree ctor = lookup_placeholder (ctx, lval, TREE_TYPE (t)))
    2691              :         {
    2692            0 :           if (TREE_CODE (ctor) == CONSTRUCTOR)
    2693              :             return ctor;
    2694              :           else
    2695            0 :             return eval_constant_expression (ctx, ctor, lval, non_constant_p,
    2696            0 :                                              overflow_p, jump_target);
    2697              :         }
    2698              :       /* A placeholder without a referent.  We can get here when
    2699              :          checking whether NSDMIs are noexcept, or in massage_init_elt;
    2700              :          just say it's non-constant for now.  */
    2701            0 :       gcc_assert (ctx->quiet);
    2702            0 :       *non_constant_p = true;
    2703            0 :       break;
    2704              : 
    2705            0 :     case ANNOTATE_EXPR:
    2706            0 :       r = eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval,
    2707              :                                     non_constant_p, overflow_p, jump_target);
    2708            0 :       break;
    2709              : 
    2710            0 :     case ASM_EXPR:
    2711            0 :       if (!ctx->quiet)
    2712            0 :         inline_asm_in_constexpr_error (loc);
    2713            0 :       *non_constant_p = true;
    2714            0 :       return t;
    2715              : 
    2716              :     default:
    2717              :       break;
    2718              :     }
    2719              : 
    2720       535800 :   return r;
    2721              : }
    2722              : 
    2723              : /* Complain about a const object OBJ being modified in a constant expression.
    2724              :    EXPR is the MODIFY_EXPR expression performing the modification.  */
    2725              : 
    2726              : static void
    2727            0 : modifying_const_object_error (tree expr, tree obj)
    2728              : {
    2729            0 :   location_t loc = EXPR_LOCATION (expr);
    2730            0 :   auto_diagnostic_group d;
    2731            0 :   error_at (loc,
    2732              :             "modifying a const object %qE is not allowed in "
    2733              :             "a constant expression",
    2734            0 :             TREE_OPERAND (expr, 0));
    2735            0 :   inform (location_of (obj), "originally declared %<const%> here");
    2736            0 : }
    2737              : 
    2738              : /* Return true iff DECL is an empty field, either for an empty base or a
    2739              :    [[no_unique_address]] data member.  */
    2740              : 
    2741              : bool
    2742            1 : is_empty_field (tree decl)
    2743              : {
    2744            1 :   if (!decl || TREE_CODE (decl) != FIELD_DECL)
    2745              :     return false;
    2746              : 
    2747            1 :   bool r = is_empty_class (TREE_TYPE (decl));
    2748              : 
    2749              :   /* Empty fields should have size zero.  */
    2750            1 :   gcc_checking_assert (!r || integer_zerop (DECL_SIZE (decl)));
    2751              : 
    2752              :   return r;
    2753              : }
    2754              : 
    2755              : static tree
    2756         2516 : eval_store_expression (const constexpr_ctx *ctx, tree t, bool lval,
    2757              :                        bool *non_constant_p, bool *overflow_p,
    2758              :                        tree *jump_target)
    2759              : {
    2760         2516 :   constexpr_ctx new_ctx = *ctx;
    2761              : 
    2762         2516 :   tree init = TREE_OPERAND (t, 1);
    2763         2516 :   if (TREE_CLOBBER_P (init))
    2764              :     /* Just ignore clobbers.  */
    2765            0 :     return void_node;
    2766              : 
    2767              :   /* First we figure out where we're storing to.  */
    2768         2516 :   tree target = TREE_OPERAND (t, 0);
    2769              : 
    2770         2516 :   tree type = TREE_TYPE (target);
    2771         2516 :   bool preeval = SCALAR_TYPE_P (type) || TREE_CODE (t) == MODIFY_EXPR;
    2772              :   if (preeval)
    2773              :     {
    2774              :       /* Evaluate the value to be stored without knowing what object it will be
    2775              :          stored in, so that any side-effects happen first.  */
    2776         2516 :       if (!SCALAR_TYPE_P (type))
    2777              :         {
    2778           84 :           new_ctx.ctor = new_ctx.object = NULL_TREE;
    2779           84 :           if (TREE_CODE (init) == CONSTRUCTOR)
    2780              :             {
    2781           71 :               new_ctx.ctor = build_constructor (TREE_TYPE (init), NULL);
    2782           71 :               CONSTRUCTOR_NO_CLEARING (new_ctx.ctor) = true;
    2783              :             }
    2784              :         }
    2785         2516 :       init = eval_constant_expression (&new_ctx, init, false, non_constant_p,
    2786              :                                        overflow_p, jump_target);
    2787         2516 :       if (*non_constant_p)
    2788              :         return t;
    2789              :     }
    2790              : 
    2791         2500 :   bool evaluated = false;
    2792         2500 :   if (lval)
    2793              :     {
    2794              :       /* If we want to return a reference to the target, we need to evaluate it
    2795              :          as a whole; otherwise, only evaluate the innermost piece to avoid
    2796              :          building up unnecessary *_REFs.  */
    2797            0 :       target = eval_constant_expression (ctx, target, true, non_constant_p,
    2798              :                                          overflow_p, jump_target);
    2799            0 :       evaluated = true;
    2800            0 :       if (*non_constant_p)
    2801              :         return t;
    2802              :     }
    2803              : 
    2804              :   /* Find the underlying variable.  */
    2805         2500 :   releasing_vec refs;
    2806         2500 :   tree object = NULL_TREE;
    2807              :   /* If we're modifying a const object, save it.  */
    2808         2500 :   tree const_object_being_modified = NULL_TREE;
    2809              :   // bool mutable_p = false;
    2810         7502 :   for (tree probe = target; object == NULL_TREE;)
    2811              :     {
    2812         5002 :       switch (TREE_CODE (probe))
    2813              :         {
    2814            2 :         case BIT_FIELD_REF:
    2815            2 :         case COMPONENT_REF:
    2816            2 :         case ARRAY_REF:
    2817            2 :           {
    2818            2 :             tree ob = TREE_OPERAND (probe, 0);
    2819            2 :             tree elt = TREE_OPERAND (probe, 1);
    2820            2 :             if (TREE_CODE (elt) == FIELD_DECL /*&& DECL_MUTABLE_P (elt)*/)
    2821              :               {
    2822              :                 // mutable_p = true;
    2823              :               }
    2824            2 :             if (TREE_CODE (probe) == ARRAY_REF)
    2825              :               {
    2826            1 :                 elt = eval_and_check_array_index (ctx, probe, false,
    2827              :                                                   non_constant_p, overflow_p,
    2828              :                                                   jump_target);
    2829            1 :                 if (*non_constant_p)
    2830            0 :                   return t;
    2831              :               }
    2832              :             /* We don't check modifying_const_object_p for ARRAY_REFs.  Given
    2833              :                "int a[10]", an ARRAY_REF "a[2]" can be "const int", even though
    2834              :                the array isn't const.  Instead, check "a" in the next iteration;
    2835              :                that will detect modifying "const int a[10]".  */
    2836              :             // else if (evaluated
    2837              :             //          && modifying_const_object_p (TREE_CODE (t), probe,
    2838              :             //                                    mutable_p)
    2839              :             //          && const_object_being_modified == NULL_TREE)
    2840              :             //   const_object_being_modified = probe;
    2841            2 :             vec_safe_push (refs, elt);
    2842            2 :             vec_safe_push (refs, TREE_TYPE (probe));
    2843            2 :             probe = ob;
    2844              :           }
    2845            2 :           break;
    2846              : 
    2847         5000 :         default:
    2848         5000 :           if (evaluated)
    2849         2500 :             object = probe;
    2850              :           else
    2851              :             {
    2852         2500 :               probe
    2853         2500 :                 = eval_constant_expression (ctx, probe, true, non_constant_p,
    2854              :                                             overflow_p, jump_target);
    2855         2500 :               evaluated = true;
    2856         2500 :               if (*non_constant_p)
    2857              :                 return t;
    2858              :             }
    2859              :           break;
    2860              :         }
    2861              :     }
    2862              : 
    2863              :   // if (modifying_const_object_p (TREE_CODE (t), object, mutable_p)
    2864              :   //   && const_object_being_modified == NULL_TREE)
    2865              :   // const_object_being_modified = object;
    2866              : 
    2867              :   /* And then find/build up our initializer for the path to the subobject
    2868              :      we're initializing.  */
    2869         2500 :   tree *valp;
    2870         2500 :   if (DECL_P (object))
    2871         2500 :     valp = ctx->global->values.get (object);
    2872              :   else
    2873              :     valp = NULL;
    2874         2500 :   if (!valp)
    2875              :     {
    2876              :       /* A constant-expression cannot modify objects from outside the
    2877              :          constant-expression.  */
    2878            0 :       if (!ctx->quiet)
    2879            0 :         error ("modification of %qE is not a constant expression", object);
    2880            0 :       *non_constant_p = true;
    2881            0 :       return t;
    2882              :     }
    2883         2500 :   type = TREE_TYPE (object);
    2884         2500 :   bool no_zero_init = true;
    2885              : 
    2886         5000 :   releasing_vec ctors, indexes;
    2887         5000 :   auto_vec<int> index_pos_hints;
    2888         2500 :   bool activated_union_member_p = false;
    2889         2502 :   while (!refs->is_empty ())
    2890              :     {
    2891            2 :       if (*valp == NULL_TREE)
    2892              :         {
    2893            0 :           *valp = build_constructor (type, NULL);
    2894            0 :           CONSTRUCTOR_NO_CLEARING (*valp) = no_zero_init;
    2895              :         }
    2896            2 :       else if (TREE_CODE (*valp) == STRING_CST)
    2897              :         {
    2898              :           /* An array was initialized with a string constant, and now
    2899              :              we're writing into one of its elements.  Explode the
    2900              :              single initialization into a set of element
    2901              :              initializations.  */
    2902            0 :           gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
    2903              : 
    2904            0 :           tree string = *valp;
    2905            0 :           tree elt_type = TREE_TYPE (type);
    2906            0 :           unsigned chars_per_elt
    2907            0 :             = (TYPE_PRECISION (elt_type) / TYPE_PRECISION (char_type_node));
    2908            0 :           unsigned num_elts = TREE_STRING_LENGTH (string) / chars_per_elt;
    2909            0 :           tree ary_ctor = build_constructor (type, NULL);
    2910              : 
    2911            0 :           vec_safe_reserve (CONSTRUCTOR_ELTS (ary_ctor), num_elts);
    2912            0 :           for (unsigned ix = 0; ix != num_elts; ix++)
    2913              :             {
    2914            0 :               constructor_elt elt
    2915            0 :                 = {build_int_cst (size_type_node, ix),
    2916            0 :                    extract_string_elt (string, chars_per_elt, ix)};
    2917            0 :               CONSTRUCTOR_ELTS (ary_ctor)->quick_push (elt);
    2918              :             }
    2919              : 
    2920            0 :           *valp = ary_ctor;
    2921              :         }
    2922              : 
    2923              :       /* If the value of object is already zero-initialized, any new ctors for
    2924              :          subobjects will also be zero-initialized.  */
    2925            2 :       no_zero_init = CONSTRUCTOR_NO_CLEARING (*valp);
    2926              : 
    2927            2 :       enum tree_code code = TREE_CODE (type);
    2928            2 :       type = refs->pop ();
    2929            2 :       tree index = refs->pop ();
    2930              : 
    2931            2 :       if (code == RECORD_TYPE && is_empty_field (index))
    2932              :         /* Don't build a sub-CONSTRUCTOR for an empty base or field, as they
    2933              :            have no data and might have an offset lower than previously declared
    2934              :            fields, which confuses the middle-end.  The code below will notice
    2935              :            that we don't have a CONSTRUCTOR for our inner target and just
    2936              :            return init.  */
    2937              :         break;
    2938              : 
    2939            0 :       if (code == UNION_TYPE && CONSTRUCTOR_NELTS (*valp)
    2940            2 :           && CONSTRUCTOR_ELT (*valp, 0)->index != index)
    2941              :         {
    2942            0 :           if (TREE_CODE (t) == MODIFY_EXPR && CONSTRUCTOR_NO_CLEARING (*valp))
    2943              :             {
    2944              :               /* Diagnose changing the active union member while the union
    2945              :                  is in the process of being initialized.  */
    2946            0 :               if (!ctx->quiet)
    2947            0 :                 error_at (EXPR_LOCATION (t),
    2948              :                           "change of the active member of a union "
    2949              :                           "from %qD to %qD during initialization",
    2950            0 :                           CONSTRUCTOR_ELT (*valp, 0)->index, index);
    2951            0 :               *non_constant_p = true;
    2952              :             }
    2953              :           no_zero_init = true;
    2954              :         }
    2955              : 
    2956            2 :       vec_safe_push (ctors, *valp);
    2957            2 :       vec_safe_push (indexes, index);
    2958              : 
    2959            2 :       constructor_elt *cep = get_or_insert_ctor_field (*valp, index);
    2960            2 :       index_pos_hints.safe_push (cep - CONSTRUCTOR_ELTS (*valp)->begin ());
    2961              : 
    2962            2 :       if (code == UNION_TYPE)
    2963            0 :         activated_union_member_p = true;
    2964              : 
    2965            2 :       valp = &cep->value;
    2966              :     }
    2967              : 
    2968              :   /* Detect modifying a constant object in constexpr evaluation.
    2969              :      We have found a const object that is being modified.  Figure out
    2970              :      if we need to issue an error.  Consider
    2971              : 
    2972              :      struct A {
    2973              :        int n;
    2974              :        constexpr A() : n(1) { n = 2; } // #1
    2975              :      };
    2976              :      struct B {
    2977              :        const A a;
    2978              :        constexpr B() { a.n = 3; } // #2
    2979              :      };
    2980              :     constexpr B b{};
    2981              : 
    2982              :     #1 is OK, since we're modifying an object under construction, but
    2983              :     #2 is wrong, since "a" is const and has been fully constructed.
    2984              :     To track it, we use the TREE_READONLY bit in the object's CONSTRUCTOR
    2985              :     which means that the object is read-only.  For the example above, the
    2986              :     *ctors stack at the point of #2 will look like:
    2987              : 
    2988              :       ctors[0] = {.a={.n=2}}  TREE_READONLY = 0
    2989              :       ctors[1] = {.n=2}       TREE_READONLY = 1
    2990              : 
    2991              :     and we're modifying "b.a", so we search the stack and see if the
    2992              :     constructor for "b.a" has already run.  */
    2993         2500 :   if (const_object_being_modified)
    2994              :     {
    2995              :       bool fail = false;
    2996              :       tree const_objtype
    2997              :         = strip_array_types (TREE_TYPE (const_object_being_modified));
    2998              :       if (!CLASS_TYPE_P (const_objtype))
    2999              :         fail = true;
    3000              :       else
    3001              :         {
    3002              :           /* [class.ctor]p5 "A constructor can be invoked for a const,
    3003              :              volatile, or const volatile object.  const and volatile
    3004              :              semantics are not applied on an object under construction.
    3005              :              They come into effect when the constructor for the most
    3006              :              derived object ends."  */
    3007              :           for (tree elt : *ctors)
    3008              :             if (same_type_ignoring_top_level_qualifiers_p (
    3009              :                   TREE_TYPE (const_object_being_modified), TREE_TYPE (elt)))
    3010              :               {
    3011              :                 fail = TREE_READONLY (elt);
    3012              :                 break;
    3013              :               }
    3014              :         }
    3015              :       if (fail)
    3016              :         {
    3017              :           if (!ctx->quiet)
    3018              :             modifying_const_object_error (t, const_object_being_modified);
    3019              :           *non_constant_p = true;
    3020              :           return t;
    3021              :         }
    3022              :     }
    3023              : 
    3024         2500 :   if (!preeval)
    3025              :     {
    3026              :       /* We're handling an INIT_EXPR of class type, so the value of the
    3027              :          initializer can depend on the object it's initializing.  */
    3028              : 
    3029              :       /* Create a new CONSTRUCTOR in case evaluation of the initializer
    3030              :          wants to modify it.  */
    3031            0 :       if (*valp == NULL_TREE)
    3032              :         {
    3033            0 :           *valp = build_constructor (type, NULL);
    3034            0 :           CONSTRUCTOR_NO_CLEARING (*valp) = no_zero_init;
    3035              :         }
    3036            0 :       new_ctx.ctor = *valp;
    3037            0 :       new_ctx.object = target;
    3038              :       /* Avoid temporary materialization when initializing from a TARGET_EXPR.
    3039              :          We don't need to mess with AGGR_EXPR_SLOT/VEC_INIT_EXPR_SLOT because
    3040              :          expansion of those trees uses ctx instead.  */
    3041            0 :       if (TREE_CODE (init) == TARGET_EXPR)
    3042            0 :         if (tree tinit = TARGET_EXPR_INITIAL (init))
    3043            0 :           init = tinit;
    3044            0 :       init = eval_constant_expression (&new_ctx, init, false, non_constant_p,
    3045              :                                        overflow_p, jump_target);
    3046              :       /* The hash table might have moved since the get earlier, and the
    3047              :          initializer might have mutated the underlying CONSTRUCTORs, so we must
    3048              :          recompute VALP. */
    3049            0 :       valp = ctx->global->values.get (object);
    3050            0 :       for (unsigned i = 0; i < vec_safe_length (indexes); i++)
    3051              :         {
    3052            0 :           constructor_elt *cep
    3053            0 :             = get_or_insert_ctor_field (*valp, indexes[i], index_pos_hints[i]);
    3054            0 :           valp = &cep->value;
    3055              :         }
    3056              :     }
    3057              : 
    3058         2500 :   if (*non_constant_p)
    3059              :     return t;
    3060              : 
    3061              :   /* Don't share a CONSTRUCTOR that might be changed later.  */
    3062         2500 :   init = unshare_constructor (init);
    3063         2500 :   if (init == NULL_TREE)
    3064              :     return t;
    3065              : 
    3066         2500 :   if (*valp && TREE_CODE (*valp) == CONSTRUCTOR
    3067            4 :       && TREE_CODE (init) == CONSTRUCTOR)
    3068              :     {
    3069              :       /* An outer ctx->ctor might be pointing to *valp, so replace
    3070              :          its contents.  */
    3071            4 :       if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (init),
    3072            4 :                                                       TREE_TYPE (*valp)))
    3073              :         {
    3074              :           /* For initialization of an empty base, the original target will be
    3075              :            *(base*)this, evaluation of which resolves to the object
    3076              :            argument, which has the derived type rather than the base type.  In
    3077              :            this situation, just evaluate the initializer and return, since
    3078              :            there's no actual data to store.  */
    3079            0 :           gcc_assert (is_empty_class (TREE_TYPE (init)));
    3080            0 :           return lval ? target : init;
    3081              :         }
    3082            4 :       CONSTRUCTOR_ELTS (*valp) = CONSTRUCTOR_ELTS (init);
    3083            4 :       TREE_CONSTANT (*valp) = TREE_CONSTANT (init);
    3084            4 :       TREE_SIDE_EFFECTS (*valp) = TREE_SIDE_EFFECTS (init);
    3085            4 :       CONSTRUCTOR_NO_CLEARING (*valp) = CONSTRUCTOR_NO_CLEARING (init);
    3086              :     }
    3087              :   // else if (TREE_CODE (init) == CONSTRUCTOR
    3088              :   //          && !same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (init),
    3089              :   //                                                      type))
    3090              :   //   {
    3091              :   //     /* See above on initialization of empty bases.  */
    3092              :   //     // gcc_assert (is_empty_class (TREE_TYPE (init)) && !lval);
    3093              :   //     return init;
    3094              :   //   }
    3095              :   else
    3096         2496 :     *valp = init;
    3097              : 
    3098              :   /* After initialization, 'const' semantics apply to the value of the
    3099              :      object.  Make a note of this fact by marking the CONSTRUCTOR
    3100              :      TREE_READONLY.  */
    3101            0 :   if (TREE_CODE (t) == INIT_EXPR && TREE_CODE (*valp) == CONSTRUCTOR
    3102         2500 :       && TYPE_READONLY (type))
    3103              :     {
    3104              :       // this vs self? can rust's self be anything other than self or &self in
    3105              :       // constexpr mode? if (INDIRECT_REF_P (target)
    3106              :       //     && (is_this_parameter (
    3107              :       //       tree_strip_nop_conversions (TREE_OPERAND (target, 0)))))
    3108              :       /* We've just initialized '*this' (perhaps via the target
    3109              :          constructor of a delegating constructor).  Leave it up to the
    3110              :          caller that set 'this' to set TREE_READONLY appropriately.  */
    3111              :       //   gcc_checking_assert (
    3112              :       //     same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (target),
    3113              :       //     type));
    3114              :       // else
    3115              :       //   TREE_READONLY (*valp) = true;
    3116              :     }
    3117              : 
    3118              :   /* Update TREE_CONSTANT and TREE_SIDE_EFFECTS on enclosing
    3119              :      CONSTRUCTORs, if any.  */
    3120         2500 :   bool c = TREE_CONSTANT (init);
    3121         2500 :   bool s = TREE_SIDE_EFFECTS (init);
    3122         2500 :   if (!c || s || activated_union_member_p)
    3123            4 :     for (tree elt : *ctors)
    3124              :       {
    3125            0 :         if (!c)
    3126            0 :           TREE_CONSTANT (elt) = false;
    3127            0 :         if (s)
    3128            0 :           TREE_SIDE_EFFECTS (elt) = true;
    3129              :         /* Clear CONSTRUCTOR_NO_CLEARING since we've activated a member of
    3130              :            this union.  */
    3131            0 :         if (TREE_CODE (TREE_TYPE (elt)) == UNION_TYPE)
    3132            0 :           CONSTRUCTOR_NO_CLEARING (elt) = false;
    3133              :       }
    3134              : 
    3135         2500 :   if (*non_constant_p)
    3136              :     return t;
    3137         2500 :   else if (lval)
    3138              :     return target;
    3139              :   else
    3140         2500 :     return init;
    3141         2500 : }
    3142              : 
    3143              : /* Subroutine of cxx_eval_constant_expression.
    3144              :  Like cxx_eval_unary_expression, except for binary expressions.  */
    3145              : static tree
    3146          349 : eval_binary_expression (const constexpr_ctx *ctx, tree t, bool lval,
    3147              :                         bool *non_constant_p, bool *overflow_p,
    3148              :                         tree *jump_target)
    3149              : {
    3150          349 :   tree r = NULL_TREE;
    3151          349 :   tree orig_lhs = TREE_OPERAND (t, 0);
    3152          349 :   tree orig_rhs = TREE_OPERAND (t, 1);
    3153          349 :   tree lhs, rhs;
    3154          349 :   lhs = eval_constant_expression (ctx, orig_lhs, lval, non_constant_p,
    3155              :                                   overflow_p, jump_target);
    3156              :   /* Don't VERIFY_CONSTANT here, it's unnecessary and will break pointer
    3157              :      subtraction.  */
    3158          349 :   if (*non_constant_p)
    3159              :     return t;
    3160          348 :   if (*jump_target)
    3161              :     return NULL_TREE;
    3162              : 
    3163          348 :   rhs = eval_constant_expression (ctx, orig_rhs, lval, non_constant_p,
    3164              :                                   overflow_p, jump_target);
    3165          348 :   if (*non_constant_p)
    3166              :     return t;
    3167          348 :   if (*jump_target)
    3168              :     return NULL_TREE;
    3169              : 
    3170          348 :   location_t loc = EXPR_LOCATION (t);
    3171          348 :   enum tree_code code = TREE_CODE (t);
    3172          348 :   tree type = TREE_TYPE (t);
    3173              : 
    3174          348 :   if (code == EQ_EXPR || code == NE_EXPR)
    3175              :     {
    3176           19 :       bool is_code_eq = (code == EQ_EXPR);
    3177              : 
    3178           19 :       if (TREE_CODE (lhs) == PTRMEM_CST && TREE_CODE (rhs) == PTRMEM_CST)
    3179              :         {
    3180            0 :           tree lmem = PTRMEM_CST_MEMBER (lhs);
    3181            0 :           tree rmem = PTRMEM_CST_MEMBER (rhs);
    3182            0 :           bool eq = false;
    3183            0 :           if (TREE_CODE (lmem) == TREE_CODE (rmem)
    3184            0 :               && TREE_CODE (lmem) == FIELD_DECL
    3185            0 :               && TREE_CODE (DECL_CONTEXT (lmem)) == UNION_TYPE
    3186            0 :               && same_type_p (DECL_CONTEXT (lmem), DECL_CONTEXT (rmem)))
    3187              :             /* If both refer to (possibly different) members of the same union
    3188              :                (12.3), they compare equal. */
    3189              :             eq = true;
    3190              :           // else
    3191              :           //   eq = cp_tree_equal (lhs, rhs);
    3192            0 :           r = constant_boolean_node (eq == is_code_eq, type);
    3193            0 :         }
    3194           19 :       else if ((TREE_CODE (lhs) == PTRMEM_CST || TREE_CODE (rhs) == PTRMEM_CST)
    3195           19 :                && (null_member_pointer_value_p (lhs)
    3196            0 :                    || null_member_pointer_value_p (rhs)))
    3197            0 :         r = constant_boolean_node (!is_code_eq, type);
    3198              :     }
    3199          348 :   if (r == NULL_TREE && TREE_CODE_CLASS (code) == tcc_comparison
    3200           30 :       && POINTER_TYPE_P (TREE_TYPE (lhs)))
    3201              :     {
    3202            1 :       lhs = maybe_fold_reference_address_to_pointer (lhs);
    3203            1 :       rhs = maybe_fold_reference_address_to_pointer (rhs);
    3204              : 
    3205            1 :       if (tree lhso = maybe_fold_addr_pointer_plus (lhs))
    3206            0 :         lhs = fold_convert (TREE_TYPE (lhs), lhso);
    3207            1 :       if (tree rhso = maybe_fold_addr_pointer_plus (rhs))
    3208            0 :         rhs = fold_convert (TREE_TYPE (rhs), rhso);
    3209              :     }
    3210            0 :   if (code == POINTER_PLUS_EXPR && !*non_constant_p && integer_zerop (lhs)
    3211          348 :       && !integer_zerop (rhs))
    3212              :     {
    3213            0 :       if (!ctx->quiet)
    3214            0 :         error ("arithmetic involving a null pointer in %qE", lhs);
    3215            0 :       *non_constant_p = true;
    3216            0 :       return t;
    3217              :     }
    3218          348 :   else if (code == POINTER_PLUS_EXPR)
    3219              :     {
    3220            0 :       r = fold_pointer_plus_expression (ctx, t, lhs, rhs, non_constant_p,
    3221              :                                         overflow_p, jump_target);
    3222            0 :       if (*jump_target)
    3223              :         return NULL_TREE;
    3224              :     }
    3225              : 
    3226          348 :   if (r == NULL_TREE)
    3227              :     {
    3228          348 :       if (ctx->manifestly_const_eval && TREE_CODE (type) != REAL_TYPE)
    3229          334 :         r = fold_binary_initializer_loc (loc, code, type, lhs, rhs);
    3230              :       else
    3231           14 :         r = fold_binary_loc (loc, code, type, lhs, rhs);
    3232              :     }
    3233              : 
    3234            2 :   if (r == NULL_TREE && (code == LSHIFT_EXPR || code == RSHIFT_EXPR)
    3235            0 :       && TREE_CODE (lhs) == INTEGER_CST && TREE_CODE (rhs) == INTEGER_CST
    3236          350 :       && wi::neg_p (wi::to_wide (rhs)))
    3237              :     {
    3238              :       /* For diagnostics and -fpermissive emulate previous behavior of
    3239              :          handling shifts by negative amount.  */
    3240            0 :       tree nrhs = const_unop (NEGATE_EXPR, TREE_TYPE (rhs), rhs);
    3241            0 :       if (nrhs)
    3242            0 :         r = fold_binary_loc (loc,
    3243              :                              code == LSHIFT_EXPR ? RSHIFT_EXPR : LSHIFT_EXPR,
    3244              :                              type, lhs, nrhs);
    3245              :     }
    3246              : 
    3247          348 :   if (r == NULL_TREE)
    3248              :     {
    3249            2 :       if (lhs == orig_lhs && rhs == orig_rhs)
    3250              :         r = t;
    3251              :       else
    3252            0 :         r = build2_loc (loc, code, type, lhs, rhs);
    3253              :     }
    3254          346 :   else if (eval_check_shift_p (loc, ctx, code, type, lhs, rhs))
    3255            0 :     *non_constant_p = true;
    3256          346 :   else if (eval_check_overflow_p (loc, ctx, code, type, lhs, rhs))
    3257              :     {
    3258           11 :       *non_constant_p = true;
    3259              :       /* The overflow has been diagnosed here, with a location.  Clear the
    3260              :          flag so that the generic TREE_OVERFLOW check in
    3261              :          eval_constant_expression does not report it a second time against
    3262              :          the folded constant, which carries no location.  */
    3263           11 :       if (r != NULL_TREE && CONSTANT_CLASS_P (r))
    3264           11 :         TREE_OVERFLOW (r) = false;
    3265              :     }
    3266              :   /* Don't VERIFY_CONSTANT if this might be dealing with a pointer to
    3267              :      a local array in a constexpr function.  */
    3268          348 :   bool ptr = INDIRECT_TYPE_P (TREE_TYPE (lhs));
    3269          347 :   if (!ptr)
    3270          347 :     VERIFY_CONSTANT (r);
    3271              :   return r;
    3272              : }
    3273              : 
    3274              : /* Helper function of cxx_bind_parameters_in_call.  Return non-NULL
    3275              :    if *TP is address of a static variable (or part of it) currently being
    3276              :    constructed or of a heap artificial variable.  */
    3277              : 
    3278              : static tree
    3279           24 : addr_of_non_const_var (tree *tp, int *walk_subtrees, void *data)
    3280              : {
    3281           24 :   if (TREE_CODE (*tp) == ADDR_EXPR)
    3282            4 :     if (tree var = get_base_address (TREE_OPERAND (*tp, 0)))
    3283            4 :       if (VAR_P (var) && TREE_STATIC (var))
    3284              :         {
    3285            0 :           if (DECL_NAME (var) == heap_uninit_identifier
    3286            0 :               || DECL_NAME (var) == heap_identifier
    3287            0 :               || DECL_NAME (var) == heap_vec_uninit_identifier
    3288            0 :               || DECL_NAME (var) == heap_vec_identifier)
    3289            0 :             return var;
    3290              : 
    3291            0 :           constexpr_global_ctx *global = (constexpr_global_ctx *) data;
    3292            0 :           if (global->values.get (var))
    3293              :             return var;
    3294              :         }
    3295           24 :   if (TYPE_P (*tp))
    3296            0 :     *walk_subtrees = false;
    3297              :   return NULL_TREE;
    3298              : }
    3299              : 
    3300              : /* Subroutine of cxx_eval_call_expression.
    3301              :    We are processing a call expression (either CALL_EXPR or
    3302              :    AGGR_INIT_EXPR) in the context of CTX.  Evaluate
    3303              :    all arguments and bind their values to correspondings
    3304              :    parameters, making up the NEW_CALL context.  */
    3305              : 
    3306              : static tree
    3307         2405 : rs_bind_parameters_in_call (const constexpr_ctx *ctx, tree t, tree fun,
    3308              :                             bool *non_constant_p, bool *overflow_p,
    3309              :                             bool *non_constant_args, tree *jump_target)
    3310              : {
    3311         2405 :   const int nargs = call_expr_nargs (t);
    3312         2405 :   tree parms = DECL_ARGUMENTS (fun);
    3313         2405 :   int i;
    3314              :   /* We don't record ellipsis args below.  */
    3315         2405 :   int nparms = list_length (parms);
    3316         2405 :   int nbinds = nargs < nparms ? nargs : nparms;
    3317         2405 :   tree binds = make_tree_vec (nbinds);
    3318         4826 :   for (i = 0; i < nargs; ++i)
    3319              :     {
    3320           16 :       tree x, arg;
    3321           16 :       tree type = parms ? TREE_TYPE (parms) : void_type_node;
    3322           16 :       if (parms && DECL_BY_REFERENCE (parms))
    3323            0 :         type = TREE_TYPE (type);
    3324           16 :       x = CALL_EXPR_ARG (t, i);
    3325              : 
    3326           16 :       if (TREE_ADDRESSABLE (type))
    3327              :         /* Undo convert_for_arg_passing work here.  */
    3328            0 :         x = convert_from_reference (x);
    3329              :       /* Normally we would strip a TARGET_EXPR in an initialization context
    3330              :          such as this, but here we do the elision differently: we keep the
    3331              :          TARGET_EXPR, and use its CONSTRUCTOR as the value of the parm.  */
    3332           16 :       arg = eval_constant_expression (ctx, x, /*lval=*/false, non_constant_p,
    3333              :                                       overflow_p, jump_target);
    3334              :       /* Don't VERIFY_CONSTANT here.  */
    3335           16 :       if (*non_constant_p && ctx->quiet)
    3336              :         break;
    3337              :       /* Just discard ellipsis args after checking their constantitude.  */
    3338           16 :       if (!parms)
    3339            0 :         continue;
    3340              : 
    3341           16 :       if (!*non_constant_p)
    3342              :         {
    3343              :           /* Make sure the binding has the same type as the parm.  But
    3344              :              only for constant args.  */
    3345           16 :           if (!TYPE_REF_P (type))
    3346           14 :             arg = adjust_temp_type (type, arg);
    3347           16 :           if (!TREE_CONSTANT (arg))
    3348            0 :             *non_constant_args = true;
    3349           16 :           else if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
    3350              :             /* The destructor needs to see any modifications the callee makes
    3351              :                to the argument.  */
    3352            0 :             *non_constant_args = true;
    3353              :           /* If arg is or contains address of a heap artificial variable or
    3354              :              of a static variable being constructed, avoid caching the
    3355              :              function call, as those variables might be modified by the
    3356              :              function, or might be modified by the callers in between
    3357              :              the cached function and just read by the function.  */
    3358           16 :           else if (!*non_constant_args
    3359           16 :                    && rs_walk_tree (&arg, addr_of_non_const_var, ctx->global,
    3360              :                                     NULL))
    3361            0 :             *non_constant_args = true;
    3362              : 
    3363              :           // /* For virtual calls, adjust the this argument, so that it is
    3364              :           //    the object on which the method is called, rather than
    3365              :           //    one of its bases.  */
    3366              :           // if (i == 0 && DECL_VIRTUAL_P (fun))
    3367              :           //   {
    3368              :           //     tree addr = arg;
    3369              :           //     STRIP_NOPS (addr);
    3370              :           //     if (TREE_CODE (addr) == ADDR_EXPR)
    3371              :           //       {
    3372              :           //         tree obj = TREE_OPERAND (addr, 0);
    3373              :           //         while (TREE_CODE (obj) == COMPONENT_REF
    3374              :           //             && DECL_FIELD_IS_BASE (TREE_OPERAND (obj, 1))
    3375              :           //             && !same_type_ignoring_top_level_qualifiers_p (
    3376              :           //               TREE_TYPE (obj), DECL_CONTEXT (fun)))
    3377              :           //           obj = TREE_OPERAND (obj, 0);
    3378              :           //         if (obj != TREE_OPERAND (addr, 0))
    3379              :           //           arg = build_fold_addr_expr_with_type (obj, TREE_TYPE
    3380              :           //           (arg));
    3381              :           //       }
    3382              :           //   }
    3383           16 :           TREE_VEC_ELT (binds, i) = arg;
    3384              :         }
    3385           16 :       parms = TREE_CHAIN (parms);
    3386              :     }
    3387              : 
    3388         2405 :   return binds;
    3389              : }
    3390              : 
    3391              : // forked from gcc/cp/constexpr.cc cxx_eval_builtin_function_call
    3392              : 
    3393              : /* Attempt to evaluate T which represents a call to a builtin function.
    3394              :    We assume here that all builtin functions evaluate to scalar types
    3395              :    represented by _CST nodes.  */
    3396              : 
    3397              : static tree
    3398            0 : eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,
    3399              :                             bool lval, bool *non_constant_p, bool *overflow_p,
    3400              :                             tree *jump_target)
    3401              : {
    3402            0 :   const int nargs = call_expr_nargs (t);
    3403            0 :   tree *args = (tree *) alloca (nargs * sizeof (tree));
    3404            0 :   tree new_call;
    3405            0 :   int i;
    3406              : 
    3407              :   /* Don't fold __builtin_constant_p within a constexpr function.  */
    3408            0 :   bool bi_const_p = DECL_IS_BUILTIN_CONSTANT_P (fun);
    3409              : 
    3410              :   /* If we aren't requiring a constant expression, defer __builtin_constant_p
    3411              :      in a constexpr function until we have values for the parameters.  */
    3412            0 :   if (bi_const_p && !ctx->manifestly_const_eval && current_function_decl
    3413            0 :       && DECL_DECLARED_CONSTEXPR_P (current_function_decl))
    3414              :     {
    3415            0 :       *non_constant_p = true;
    3416            0 :       return t;
    3417              :     }
    3418              : 
    3419              :   /* For __builtin_is_constant_evaluated, defer it if not
    3420              :      ctx->manifestly_const_eval (as sometimes we try to constant evaluate
    3421              :      without manifestly_const_eval even expressions or parts thereof which
    3422              :      will later be manifestly const_eval evaluated), otherwise fold it to
    3423              :      true.  */
    3424            0 :   if (fndecl_built_in_p (fun, CP_BUILT_IN_IS_CONSTANT_EVALUATED,
    3425              :                          BUILT_IN_FRONTEND))
    3426              :     {
    3427            0 :       if (!ctx->manifestly_const_eval)
    3428              :         {
    3429            0 :           *non_constant_p = true;
    3430            0 :           return t;
    3431              :         }
    3432            0 :       return boolean_true_node;
    3433              :     }
    3434              : 
    3435            0 :   if (fndecl_built_in_p (fun, CP_BUILT_IN_SOURCE_LOCATION, BUILT_IN_FRONTEND))
    3436              :     {
    3437            0 :       temp_override<tree> ovr (current_function_decl);
    3438            0 :       if (ctx->call && ctx->call->fundef)
    3439            0 :         current_function_decl = ctx->call->fundef->decl;
    3440            0 :       return fold_builtin_source_location (EXPR_LOCATION (t));
    3441            0 :     }
    3442              : 
    3443            0 :   int strops = 0;
    3444            0 :   int strret = 0;
    3445            0 :   if (fndecl_built_in_p (fun, BUILT_IN_NORMAL))
    3446            0 :     switch (DECL_FUNCTION_CODE (fun))
    3447              :       {
    3448              :       case BUILT_IN_STRLEN:
    3449              :       case BUILT_IN_STRNLEN:
    3450            0 :         strops = 1;
    3451              :         break;
    3452            0 :       case BUILT_IN_MEMCHR:
    3453            0 :       case BUILT_IN_STRCHR:
    3454            0 :       case BUILT_IN_STRRCHR:
    3455            0 :         strops = 1;
    3456            0 :         strret = 1;
    3457            0 :         break;
    3458            0 :       case BUILT_IN_MEMCMP:
    3459            0 :       case BUILT_IN_STRCMP:
    3460            0 :         strops = 2;
    3461            0 :         break;
    3462            0 :       case BUILT_IN_STRSTR:
    3463            0 :         strops = 2;
    3464            0 :         strret = 1;
    3465            0 :         break;
    3466            0 :       case BUILT_IN_ASAN_POINTER_COMPARE:
    3467            0 :       case BUILT_IN_ASAN_POINTER_SUBTRACT:
    3468              :         /* These builtins shall be ignored during constant expression
    3469              :            evaluation.  */
    3470            0 :         return void_node;
    3471              :       default:
    3472              :         break;
    3473              :       }
    3474              : 
    3475              :   /* Be permissive for arguments to built-ins; __builtin_constant_p should
    3476              :      return constant false for a non-constant argument.  */
    3477            0 :   constexpr_ctx new_ctx = *ctx;
    3478            0 :   new_ctx.quiet = true;
    3479            0 :   for (i = 0; i < nargs; ++i)
    3480              :     {
    3481            0 :       tree arg = CALL_EXPR_ARG (t, i);
    3482            0 :       tree oarg = arg;
    3483              : 
    3484              :       /* To handle string built-ins we need to pass ADDR_EXPR<STRING_CST> since
    3485              :          expand_builtin doesn't know how to look in the values table.  */
    3486            0 :       bool strop = i < strops;
    3487            0 :       if (strop)
    3488              :         {
    3489            0 :           STRIP_NOPS (arg);
    3490            0 :           if (TREE_CODE (arg) == ADDR_EXPR)
    3491            0 :             arg = TREE_OPERAND (arg, 0);
    3492              :           else
    3493              :             strop = false;
    3494              :         }
    3495              : 
    3496              :       /* If builtin_valid_in_constant_expr_p is true,
    3497              :          potential_constant_expression_1 has not recursed into the arguments
    3498              :          of the builtin, verify it here.  */
    3499            0 :       if (!builtin_valid_in_constant_expr_p (fun)
    3500            0 :           || potential_constant_expression (arg))
    3501              :         {
    3502            0 :           bool dummy1 = false, dummy2 = false;
    3503            0 :           tree dummy_jump_target = NULL_TREE;
    3504            0 :           arg = eval_constant_expression (&new_ctx, arg, false, &dummy1,
    3505              :                                           &dummy2, &dummy_jump_target);
    3506              :         }
    3507              : 
    3508            0 :       if (bi_const_p)
    3509              :         /* For __builtin_constant_p, fold all expressions with constant values
    3510              :            even if they aren't C++ constant-expressions.  */
    3511            0 :         arg = cp_fold_rvalue (arg);
    3512            0 :       else if (strop)
    3513              :         {
    3514            0 :           if (TREE_CODE (arg) == CONSTRUCTOR)
    3515            0 :             arg = braced_lists_to_strings (TREE_TYPE (arg), arg);
    3516            0 :           if (TREE_CODE (arg) == STRING_CST)
    3517            0 :             arg = build_address (arg);
    3518              :           else
    3519              :             arg = oarg;
    3520              :         }
    3521              : 
    3522            0 :       args[i] = arg;
    3523              :     }
    3524              : 
    3525            0 :   bool save_ffbcp = force_folding_builtin_constant_p;
    3526            0 :   force_folding_builtin_constant_p |= ctx->manifestly_const_eval;
    3527            0 :   tree save_cur_fn = current_function_decl;
    3528              :   /* Return name of ctx->call->fundef->decl for __builtin_FUNCTION ().  */
    3529            0 :   if (fndecl_built_in_p (fun, BUILT_IN_FUNCTION) && ctx->call
    3530            0 :       && ctx->call->fundef)
    3531            0 :     current_function_decl = ctx->call->fundef->decl;
    3532            0 :   if (fndecl_built_in_p (fun,
    3533              :                          CP_BUILT_IN_IS_POINTER_INTERCONVERTIBLE_WITH_CLASS,
    3534              :                          BUILT_IN_FRONTEND))
    3535              :     {
    3536            0 :       location_t loc = EXPR_LOCATION (t);
    3537            0 :       if (nargs >= 1)
    3538            0 :         VERIFY_CONSTANT (args[0]);
    3539            0 :       new_call
    3540            0 :         = fold_builtin_is_pointer_inverconvertible_with_class (loc, nargs,
    3541              :                                                                args);
    3542              :     }
    3543            0 :   else if (fndecl_built_in_p (fun, CP_BUILT_IN_IS_CORRESPONDING_MEMBER,
    3544              :                               BUILT_IN_FRONTEND))
    3545              :     {
    3546            0 :       location_t loc = EXPR_LOCATION (t);
    3547            0 :       if (nargs >= 2)
    3548              :         {
    3549            0 :           VERIFY_CONSTANT (args[0]);
    3550            0 :           VERIFY_CONSTANT (args[1]);
    3551              :         }
    3552            0 :       new_call = fold_builtin_is_corresponding_member (loc, nargs, args);
    3553              :     }
    3554              :   else
    3555            0 :     new_call = fold_builtin_call_array (EXPR_LOCATION (t), TREE_TYPE (t),
    3556            0 :                                         CALL_EXPR_FN (t), nargs, args);
    3557            0 :   current_function_decl = save_cur_fn;
    3558            0 :   force_folding_builtin_constant_p = save_ffbcp;
    3559            0 :   if (new_call == NULL)
    3560              :     {
    3561            0 :       if (!*non_constant_p && !ctx->quiet)
    3562              :         {
    3563              :           /* Do not allow__builtin_unreachable in constexpr function.
    3564              :              The __builtin_unreachable call with BUILTINS_LOCATION
    3565              :              comes from cp_maybe_instrument_return.  */
    3566            0 :           if (fndecl_built_in_p (fun, BUILT_IN_UNREACHABLE)
    3567            0 :               && EXPR_LOCATION (t) == BUILTINS_LOCATION)
    3568            0 :             error ("%<constexpr%> call flows off the end of the function");
    3569              :           else
    3570              :             {
    3571            0 :               new_call = build_call_array_loc (EXPR_LOCATION (t), TREE_TYPE (t),
    3572            0 :                                                CALL_EXPR_FN (t), nargs, args);
    3573            0 :               error ("%q+E is not a constant expression", new_call);
    3574              :             }
    3575              :         }
    3576            0 :       *non_constant_p = true;
    3577            0 :       return t;
    3578              :     }
    3579              : 
    3580            0 :   if (!potential_constant_expression (new_call))
    3581              :     {
    3582            0 :       if (!*non_constant_p && !ctx->quiet)
    3583            0 :         error ("%q+E is not a constant expression", new_call);
    3584            0 :       *non_constant_p = true;
    3585            0 :       return t;
    3586              :     }
    3587              : 
    3588            0 :   if (strret)
    3589              :     {
    3590              :       /* memchr returns a pointer into the first argument, but we replaced the
    3591              :          argument above with a STRING_CST; put it back it now.  */
    3592            0 :       tree op = CALL_EXPR_ARG (t, strret - 1);
    3593            0 :       STRIP_NOPS (new_call);
    3594            0 :       if (TREE_CODE (new_call) == POINTER_PLUS_EXPR)
    3595            0 :         TREE_OPERAND (new_call, 0) = op;
    3596            0 :       else if (TREE_CODE (new_call) == ADDR_EXPR)
    3597            0 :         new_call = op;
    3598              :     }
    3599              : 
    3600            0 :   return eval_constant_expression (&new_ctx, new_call, lval, non_constant_p,
    3601            0 :                                    overflow_p, jump_target);
    3602              : }
    3603              : 
    3604              : // Subroutine of cxx_eval_constant_expression.
    3605              : // Evaluate the call expression tree T in the context of OLD_CALL expression
    3606              : // evaluation.
    3607              : static tree
    3608         2405 : eval_call_expression (const constexpr_ctx *ctx, tree t, bool lval,
    3609              :                       bool *non_constant_p, bool *overflow_p, tree *jump_target)
    3610              : {
    3611         2405 :   location_t loc = EXPR_LOCATION (t);
    3612         2405 :   tree fun = get_function_named_in_call (t);
    3613         2405 :   rust_constexpr_call new_call
    3614         2405 :     = {NULL, NULL, NULL, 0, ctx->manifestly_const_eval};
    3615         2405 :   int depth_ok;
    3616              : 
    3617         2405 :   if (fun == NULL_TREE)
    3618              :     {
    3619              :       // return cxx_eval_internal_function (ctx, t, lval,
    3620              :       //                               non_constant_p, overflow_p);
    3621            0 :       rust_unreachable ();
    3622              :       return error_mark_node;
    3623              :     }
    3624              : 
    3625         2405 :   if (TREE_CODE (fun) != FUNCTION_DECL)
    3626              :     {
    3627            0 :       if (!ctx->quiet && !*non_constant_p)
    3628            0 :         error_at (loc,
    3629              :                   "expression %qE does not designate a %<constexpr%> "
    3630              :                   "function",
    3631              :                   fun);
    3632            0 :       *non_constant_p = true;
    3633            0 :       return t;
    3634              :     }
    3635              : 
    3636         2405 :   if (fndecl_built_in_p (fun))
    3637            0 :     return eval_builtin_function_call (ctx, t, fun, lval, non_constant_p,
    3638            0 :                                        overflow_p, jump_target);
    3639              : 
    3640         2405 :   bool non_constant_args = false;
    3641         2405 :   new_call.bindings
    3642         2405 :     = rs_bind_parameters_in_call (ctx, t, fun, non_constant_p, overflow_p,
    3643              :                                   &non_constant_args, jump_target);
    3644              : 
    3645              :   /* We build up the bindings list before we know whether we already have this
    3646              :    call cached.  If we don't end up saving these bindings, ggc_free them when
    3647              :    this function exits.  */
    3648         2405 :   class free_bindings
    3649              :   {
    3650              :     tree *bindings;
    3651              : 
    3652              :   public:
    3653         2405 :     free_bindings (tree &b) : bindings (&b) {}
    3654         2405 :     ~free_bindings ()
    3655              :     {
    3656         2405 :       if (bindings)
    3657            0 :         ggc_free (*bindings);
    3658         2405 :     }
    3659         2405 :     void preserve () { bindings = NULL; }
    3660         2405 :   } fb (new_call.bindings);
    3661              : 
    3662         2405 :   if (*non_constant_p)
    3663              :     return t;
    3664              : 
    3665              :   /* If in direct recursive call, optimize definition search.  */
    3666         2405 :   if (ctx && ctx->call && ctx->call->fundef && ctx->call->fundef->decl == fun)
    3667            0 :     new_call.fundef = ctx->call->fundef;
    3668              :   else
    3669              :     {
    3670         2405 :       new_call.fundef = retrieve_constexpr_fundef (fun);
    3671         2405 :       if (new_call.fundef == NULL || new_call.fundef->body == NULL
    3672         2405 :           || new_call.fundef->result == error_mark_node
    3673         2405 :           || fun == current_function_decl)
    3674              :         {
    3675            0 :           if (!ctx->quiet)
    3676              :             {
    3677              :               /* We need to check for current_function_decl here in case we're
    3678              :                  being called during cp_fold_function, because at that point
    3679              :                  DECL_INITIAL is set properly and we have a fundef but we
    3680              :                  haven't lowered invisirefs yet (c++/70344).  */
    3681            0 :               if (DECL_INITIAL (fun) == error_mark_node
    3682            0 :                   || fun == current_function_decl)
    3683            0 :                 error_at (loc,
    3684              :                           "%qD called in a constant expression before its "
    3685              :                           "definition is complete",
    3686              :                           fun);
    3687            0 :               else if (DECL_INITIAL (fun))
    3688              :                 {
    3689              :                   // /* The definition of fun was somehow unsuitable.  But
    3690              :                   // pretend
    3691              :                   //    that lambda static thunks don't exist.  */
    3692              :                   // if (!lambda_static_thunk_p (fun))
    3693              :                   //   error_at (loc, "%qD called in a constant expression",
    3694              :                   //   fun);
    3695            0 :                   explain_invalid_constexpr_fn (fun);
    3696              :                 }
    3697              :               else
    3698            0 :                 error_at (loc, "%qD used before its definition", fun);
    3699              :             }
    3700            0 :           *non_constant_p = true;
    3701            0 :           return t;
    3702              :         }
    3703              :     }
    3704              : 
    3705         2405 :   depth_ok = push_cx_call_context (t);
    3706              : 
    3707         2405 :   tree result = NULL_TREE;
    3708         2405 :   rust_constexpr_call *entry = NULL;
    3709         2405 :   if (depth_ok && !non_constant_args && ctx->strict)
    3710              :     {
    3711         2405 :       new_call.hash = rust_constexpr_fundef_hasher::hash (new_call.fundef);
    3712         2405 :       new_call.hash = iterative_hash_object (new_call.bindings, new_call.hash);
    3713         2405 :       new_call.hash
    3714         2405 :         = iterative_hash_object (ctx->manifestly_const_eval, new_call.hash);
    3715              : 
    3716              :       /* If we have seen this call before, we are done.  */
    3717         2405 :       maybe_initialize_constexpr_call_table ();
    3718         2405 :       rust_constexpr_call **slot
    3719         2405 :         = constexpr_call_table->find_slot (&new_call, INSERT);
    3720         2405 :       entry = *slot;
    3721         2405 :       if (entry == NULL)
    3722              :         {
    3723              :           /* Only cache up to constexpr_cache_depth to limit memory use.  */
    3724         2405 :           if (depth_ok < constexpr_cache_depth)
    3725              :             {
    3726              :               /* We need to keep a pointer to the entry, not just the slot, as
    3727              :                  the slot can move during evaluation of the body.  */
    3728         2405 :               *slot = entry = ggc_alloc<rust_constexpr_call> ();
    3729         2405 :               *entry = new_call;
    3730         2405 :               fb.preserve ();
    3731              :             }
    3732              :         }
    3733              :       /* Calls that are in progress have their result set to NULL, so that we
    3734              :          can detect circular dependencies.  Now that we only cache up to
    3735              :          constexpr_cache_depth this won't catch circular dependencies that
    3736              :          start deeper, but they'll hit the recursion or ops limit.  */
    3737            0 :       else if (entry->result == NULL)
    3738              :         {
    3739            0 :           if (!ctx->quiet)
    3740            0 :             error ("call has circular dependency");
    3741            0 :           *non_constant_p = true;
    3742            0 :           entry->result = result = error_mark_node;
    3743              :         }
    3744              :       else
    3745              :         result = entry->result;
    3746              :     }
    3747              : 
    3748         2405 :   if (!depth_ok)
    3749              :     {
    3750            0 :       if (!ctx->quiet)
    3751            0 :         error ("%<constexpr%> evaluation depth exceeds maximum of %d (use "
    3752              :                "%<-fconstexpr-depth=%> to increase the maximum)",
    3753              :                max_constexpr_depth);
    3754            0 :       *non_constant_p = true;
    3755            0 :       result = error_mark_node;
    3756              :     }
    3757              :   else
    3758              :     {
    3759         2405 :       bool cacheable = true;
    3760         2405 :       if (result && result != error_mark_node)
    3761              :         /* OK */;
    3762         2405 :       else if (!DECL_SAVED_TREE (fun))
    3763              :         {
    3764              :           /* When at_eof >= 2, cgraph has started throwing away
    3765              :              DECL_SAVED_TREE, so fail quietly.  FIXME we get here because of
    3766              :              late code generation for VEC_INIT_EXPR, which needs to be
    3767              :              completely reconsidered.  */
    3768              :           // gcc_assert (at_eof >= 2 && ctx->quiet);
    3769            0 :           *non_constant_p = true;
    3770              :         }
    3771         2405 :       else if (tree copy = get_fundef_copy (new_call.fundef))
    3772              :         {
    3773         2405 :           tree body, parms, res;
    3774         2405 :           releasing_vec ctors;
    3775              : 
    3776              :           /* Reuse or create a new unshared copy of this function's body.  */
    3777         2405 :           body = TREE_PURPOSE (copy);
    3778         2405 :           parms = TREE_VALUE (copy);
    3779         2405 :           res = TREE_TYPE (copy);
    3780              : 
    3781              :           /* Associate the bindings with the remapped parms.  */
    3782         2405 :           tree bound = new_call.bindings;
    3783         2405 :           tree remapped = parms;
    3784         2421 :           for (int i = 0; i < TREE_VEC_LENGTH (bound); ++i)
    3785              :             {
    3786           16 :               tree arg = TREE_VEC_ELT (bound, i);
    3787           16 :               if (entry)
    3788              :                 {
    3789              :                   /* Unshare args going into the hash table to separate them
    3790              :                      from the caller's context, for better GC and to avoid
    3791              :                      problems with verify_gimple.  */
    3792           16 :                   arg = unshare_expr_without_location (arg);
    3793           16 :                   TREE_VEC_ELT (bound, i) = arg;
    3794              : 
    3795              :                   /* And then unshare again so the callee doesn't change the
    3796              :                      argument values in the hash table. XXX Could we unshare
    3797              :                      lazily in cxx_eval_store_expression?  */
    3798           16 :                   arg = unshare_constructor (arg);
    3799           16 :                   if (TREE_CODE (arg) == CONSTRUCTOR)
    3800            1 :                     vec_safe_push (ctors, arg);
    3801              :                 }
    3802              : 
    3803           16 :               ctx->global->values.put (remapped, arg);
    3804           16 :               remapped = DECL_CHAIN (remapped);
    3805              :             }
    3806              :           /* Add the RESULT_DECL to the values map, too.  */
    3807         2405 :           gcc_assert (!DECL_BY_REFERENCE (res));
    3808         2405 :           ctx->global->values.put (res, NULL_TREE);
    3809              : 
    3810              :           /* Track the callee's evaluated SAVE_EXPRs and TARGET_EXPRs so that
    3811              :              we can forget their values after the call.  */
    3812         2405 :           constexpr_ctx ctx_with_save_exprs = *ctx;
    3813         2405 :           auto_vec<tree, 10> save_exprs;
    3814         2405 :           ctx_with_save_exprs.save_exprs = &save_exprs;
    3815         2405 :           ctx_with_save_exprs.call = &new_call;
    3816         2405 :           unsigned save_heap_alloc_count = ctx->global->heap_vars.length ();
    3817         2405 :           unsigned save_heap_dealloc_count = ctx->global->heap_dealloc_count;
    3818              : 
    3819         2405 :           tree jump_target = NULL_TREE;
    3820         2405 :           eval_constant_expression (&ctx_with_save_exprs, body, lval,
    3821              :                                     non_constant_p, overflow_p, &jump_target);
    3822              : 
    3823         2405 :           if (VOID_TYPE_P (TREE_TYPE (res)))
    3824            0 :             result = void_node;
    3825              :           else
    3826              :             {
    3827         2405 :               result = *ctx->global->values.get (res);
    3828         2405 :               if (result == NULL_TREE && !*non_constant_p)
    3829              :                 {
    3830            8 :                   *non_constant_p = true;
    3831              :                 }
    3832              :             }
    3833              : 
    3834              :           /* Forget the saved values of the callee's SAVE_EXPRs and
    3835              :              TARGET_EXPRs.  */
    3836         7215 :           for (tree save_expr : save_exprs)
    3837            0 :             ctx->global->values.remove (save_expr);
    3838              : 
    3839              :           /* Remove the parms/result from the values map.  Is it worth
    3840              :              bothering to do this when the map itself is only live for
    3841              :              one constexpr evaluation?  If so, maybe also clear out
    3842              :              other vars from call, maybe in BIND_EXPR handling?  */
    3843         2405 :           ctx->global->values.remove (res);
    3844         2421 :           for (tree parm = parms; parm; parm = TREE_CHAIN (parm))
    3845           16 :             ctx->global->values.remove (parm);
    3846              : 
    3847              :           /* Make the unshared function copy we used available for re-use.  */
    3848         2405 :           save_fundef_copy (fun, copy);
    3849              : 
    3850              :           /* If the call allocated some heap object that hasn't been
    3851              :              deallocated during the call, or if it deallocated some heap
    3852              :              object it has not allocated, the call isn't really stateless
    3853              :              for the constexpr evaluation and should not be cached.
    3854              :              It is fine if the call allocates something and deallocates it
    3855              :              too.  */
    3856         2405 :           if (entry
    3857         4810 :               && (save_heap_alloc_count != ctx->global->heap_vars.length ()
    3858         2405 :                   || (save_heap_dealloc_count
    3859         2405 :                       != ctx->global->heap_dealloc_count)))
    3860              :             {
    3861            0 :               tree heap_var;
    3862            0 :               unsigned int i;
    3863            0 :               if ((ctx->global->heap_vars.length ()
    3864            0 :                    - ctx->global->heap_dealloc_count)
    3865            0 :                   != save_heap_alloc_count - save_heap_dealloc_count)
    3866              :                 cacheable = false;
    3867              :               else
    3868         2405 :                 FOR_EACH_VEC_ELT_FROM (ctx->global->heap_vars, i, heap_var,
    3869              :                                        save_heap_alloc_count)
    3870            0 :                   if (DECL_NAME (heap_var) != heap_deleted_identifier)
    3871              :                     {
    3872              :                       cacheable = false;
    3873              :                       break;
    3874              :                     }
    3875              :             }
    3876         2405 :         }
    3877              :       else
    3878              :         /* Couldn't get a function copy to evaluate.  */
    3879            0 :         *non_constant_p = true;
    3880              : 
    3881         2405 :       if (result == error_mark_node)
    3882            0 :         *non_constant_p = true;
    3883         2405 :       if (*non_constant_p || *overflow_p)
    3884              :         result = error_mark_node;
    3885         2380 :       else if (!result)
    3886            0 :         result = void_node;
    3887         2405 :       if (entry)
    3888         2405 :         entry->result = cacheable ? result : error_mark_node;
    3889              :     }
    3890              : 
    3891         2405 :   pop_cx_call_context ();
    3892         2405 :   return result;
    3893         2405 : }
    3894              : 
    3895              : /* Subroutine of build_data_member_initialization.  MEMBER is a COMPONENT_REF
    3896              :    for a member of an anonymous aggregate, INIT is the initializer for that
    3897              :    member, and VEC_OUTER is the vector of constructor elements for the class
    3898              :    whose constructor we are processing.  Add the initializer to the vector
    3899              :    and return true to indicate success.  */
    3900              : 
    3901              : // static bool
    3902              : // build_anon_member_initialization (tree member, tree init,
    3903              : //                                vec<constructor_elt, va_gc> **vec_outer)
    3904              : // {
    3905              : //   /* MEMBER presents the relevant fields from the inside out, but we need
    3906              : //      to build up the initializer from the outside in so that we can reuse
    3907              : //      previously built CONSTRUCTORs if this is, say, the second field in an
    3908              : //      anonymous struct.  So we use a vec as a stack.  */
    3909              : //   auto_vec<tree, 2> fields;
    3910              : //   do
    3911              : //     {
    3912              : //       fields.safe_push (TREE_OPERAND (member, 1));
    3913              : //       member = TREE_OPERAND (member, 0);
    3914              : //   } while (ANON_AGGR_TYPE_P (TREE_TYPE (member))
    3915              : //         && TREE_CODE (member) == COMPONENT_REF);
    3916              : //
    3917              : //   /* VEC has the constructor elements vector for the context of FIELD.
    3918              : //      If FIELD is an anonymous aggregate, we will push inside it.  */
    3919              : //   vec<constructor_elt, va_gc> **vec = vec_outer;
    3920              : //   tree field;
    3921              : //   while (field = fields.pop (), ANON_AGGR_TYPE_P (TREE_TYPE (field)))
    3922              : //     {
    3923              : //       tree ctor;
    3924              : //       /* If there is already an outer constructor entry for the anonymous
    3925              : //       aggregate FIELD, use it; otherwise, insert one.  */
    3926              : //       if (vec_safe_is_empty (*vec) || (*vec)->last ().index != field)
    3927              : //      {
    3928              : //        ctor = build_constructor (TREE_TYPE (field), NULL);
    3929              : //        CONSTRUCTOR_APPEND_ELT (*vec, field, ctor);
    3930              : //      }
    3931              : //       else
    3932              : //      ctor = (*vec)->last ().value;
    3933              : //       vec = &CONSTRUCTOR_ELTS (ctor);
    3934              : //     }
    3935              : //
    3936              : //   /* Now we're at the innermost field, the one that isn't an anonymous
    3937              : //      aggregate.  Add its initializer to the CONSTRUCTOR and we're done.  */
    3938              : //   gcc_assert (fields.is_empty ());
    3939              : //   CONSTRUCTOR_APPEND_ELT (*vec, field, init);
    3940              : //
    3941              : //   return true;
    3942              : // }
    3943              : 
    3944              : ///* V is a vector of constructor elements built up for the base and member
    3945              : //   initializers of a constructor for TYPE.  They need to be in increasing
    3946              : //   offset order, which they might not be yet if TYPE has a primary base
    3947              : //   which is not first in the base-clause or a vptr and at least one base
    3948              : //   all of which are non-primary.  */
    3949              : //
    3950              : // static vec<constructor_elt, va_gc> *
    3951              : // sort_constexpr_mem_initializers (tree type, vec<constructor_elt, va_gc> *v)
    3952              : //{
    3953              : //  tree pri = CLASSTYPE_PRIMARY_BINFO (type);
    3954              : //  tree field_type;
    3955              : //  unsigned i;
    3956              : //  constructor_elt *ce;
    3957              : //
    3958              : //  if (pri)
    3959              : //    field_type = BINFO_TYPE (pri);
    3960              : //  else if (TYPE_CONTAINS_VPTR_P (type))
    3961              : //    field_type = vtbl_ptr_type_node;
    3962              : //  else
    3963              : //    return v;
    3964              : //
    3965              : //  /* Find the element for the primary base or vptr and move it to the
    3966              : //     beginning of the vec.  */
    3967              : //  for (i = 0; vec_safe_iterate (v, i, &ce); ++i)
    3968              : //    if (TREE_TYPE (ce->index) == field_type)
    3969              : //      break;
    3970              : //
    3971              : //  if (i > 0 && i < vec_safe_length (v))
    3972              : //    {
    3973              : //      vec<constructor_elt, va_gc> &vref = *v;
    3974              : //      constructor_elt elt = vref[i];
    3975              : //      for (; i > 0; --i)
    3976              : //      vref[i] = vref[i - 1];
    3977              : //      vref[0] = elt;
    3978              : //    }
    3979              : //
    3980              : //  return v;
    3981              : //}
    3982              : 
    3983              : /* Subroutine of  build_constexpr_constructor_member_initializers.
    3984              :    The expression tree T represents a data member initialization
    3985              :    in a (constexpr) constructor definition.  Build a pairing of
    3986              :    the data member with its initializer, and prepend that pair
    3987              :    to the existing initialization pair INITS.  */
    3988              : 
    3989              : static bool
    3990            0 : build_data_member_initialization (tree t, vec<constructor_elt, va_gc> **vec)
    3991              : {
    3992            0 :   tree member;
    3993            0 :   if (TREE_CODE (t) == CLEANUP_POINT_EXPR)
    3994            0 :     t = TREE_OPERAND (t, 0);
    3995            0 :   if (TREE_CODE (t) == EXPR_STMT)
    3996            0 :     t = TREE_OPERAND (t, 0);
    3997            0 :   if (t == error_mark_node)
    3998              :     return false;
    3999            0 :   if (TREE_CODE (t) == STATEMENT_LIST)
    4000              :     {
    4001            0 :       for (tree stmt : tsi_range (t))
    4002            0 :         if (!build_data_member_initialization (stmt, vec))
    4003            0 :           return false;
    4004              :       return true;
    4005              :     }
    4006            0 :   if (TREE_CODE (t) == CONVERT_EXPR)
    4007            0 :     t = TREE_OPERAND (t, 0);
    4008            0 :   if (TREE_CODE (t) == INIT_EXPR
    4009              :       /* vptr initialization shows up as a MODIFY_EXPR.  In C++14 we only
    4010              :          use what this function builds for cx_check_missing_mem_inits, and
    4011              :          assignment in the ctor body doesn't count.  */
    4012            0 :       || (TREE_CODE (t) == MODIFY_EXPR))
    4013              :     {
    4014            0 :       member = TREE_OPERAND (t, 0);
    4015              :       // Faisal: not sure if we need to port over break_out_target_exprs
    4016              :       // if not, then not sure how to handle init in this case
    4017              :       // init = break_out_target_exprs (TREE_OPERAND (t, 1));
    4018              :     }
    4019            0 :   else if (TREE_CODE (t) == CALL_EXPR)
    4020              :     {
    4021            0 :       tree fn = get_callee_fndecl (t);
    4022            0 :       if (!fn || !DECL_CONSTRUCTOR_P (fn))
    4023              :         /* We're only interested in calls to subobject constructors.  */
    4024              :         return true;
    4025            0 :       member = CALL_EXPR_ARG (t, 0);
    4026              :       /* We don't use build_cplus_new here because it complains about
    4027              :          abstract bases.  Leaving the call unwrapped means that it has the
    4028              :          wrong type, but cxx_eval_constant_expression doesn't care.  */
    4029              :       // Faisal: not sure if we need to port over break_out_target_exprs
    4030              :       // if not, then not sure how to handle init in this case
    4031              :       // init = break_out_target_exprs (t);
    4032              :     }
    4033            0 :   else if (TREE_CODE (t) == BIND_EXPR)
    4034            0 :     return build_data_member_initialization (BIND_EXPR_BODY (t), vec);
    4035              :   else
    4036              :     /* Don't add anything else to the CONSTRUCTOR.  */
    4037              :     return true;
    4038            0 :   if (INDIRECT_REF_P (member))
    4039            0 :     member = TREE_OPERAND (member, 0);
    4040            0 :   if (TREE_CODE (member) == NOP_EXPR)
    4041              :     {
    4042            0 :       tree op = member;
    4043            0 :       STRIP_NOPS (op);
    4044            0 :       if (TREE_CODE (op) == ADDR_EXPR)
    4045              :         {
    4046            0 :           gcc_assert (same_type_ignoring_top_level_qualifiers_p (
    4047              :             TREE_TYPE (TREE_TYPE (op)), TREE_TYPE (TREE_TYPE (member))));
    4048              :           /* Initializing a cv-qualified member; we need to look through
    4049              :              the const_cast.  */
    4050              :           member = op;
    4051              :         }
    4052            0 :       else if (op == current_class_ptr
    4053            0 :                && (same_type_ignoring_top_level_qualifiers_p (
    4054            0 :                  TREE_TYPE (TREE_TYPE (member)), current_class_type)))
    4055              :         /* Delegating constructor.  */
    4056              :         member = op;
    4057              :       else
    4058              :         {
    4059              :           /* This is an initializer for an empty base; keep it for now so
    4060              :              we can check it in cxx_eval_bare_aggregate.  */
    4061            0 :           gcc_assert (is_empty_class (TREE_TYPE (TREE_TYPE (member))));
    4062              :         }
    4063              :     }
    4064            0 :   if (TREE_CODE (member) == ADDR_EXPR)
    4065            0 :     member = TREE_OPERAND (member, 0);
    4066            0 :   if (TREE_CODE (member) == COMPONENT_REF)
    4067              :     {
    4068            0 :       tree aggr = TREE_OPERAND (member, 0);
    4069            0 :       if (TREE_CODE (aggr) == VAR_DECL)
    4070              :         /* Initializing a local variable, don't add anything.  */
    4071              :         return true;
    4072            0 :       if (TREE_CODE (aggr) != COMPONENT_REF)
    4073              :         /* Normal member initialization.  */
    4074            0 :         member = TREE_OPERAND (member, 1);
    4075            0 :       else if (ANON_AGGR_TYPE_P (TREE_TYPE (aggr)))
    4076              :         /* Initializing a member of an anonymous union.  */
    4077            0 :         rust_sorry_at (UNDEF_LOCATION,
    4078              :                        "cannot handle value initialization yet");
    4079              :       // return build_anon_member_initialization (member, init, vec);
    4080              :       else
    4081              :         /* We're initializing a vtable pointer in a base.  Leave it as
    4082              :            COMPONENT_REF so we remember the path to get to the vfield.  */
    4083            0 :         gcc_assert (TREE_TYPE (member) == vtbl_ptr_type_node);
    4084              :     }
    4085              : 
    4086              :   /* Value-initialization can produce multiple initializers for the
    4087              :      same field; use the last one.  */
    4088            0 :   if (!vec_safe_is_empty (*vec) && (*vec)->last ().index == member)
    4089            0 :     rust_sorry_at (UNDEF_LOCATION, "cannot handle value initialization yet");
    4090              :   // (*vec)->last ().value = init;
    4091              :   else
    4092            0 :     rust_sorry_at (UNDEF_LOCATION, "cannot handle value initialization yet");
    4093              :   // CONSTRUCTOR_APPEND_ELT (*vec, member, init);
    4094              :   return true;
    4095              : }
    4096              : 
    4097              : ///* Build compile-time evalable representations of member-initializer list
    4098              : //   for a constexpr constructor.  */
    4099              : //
    4100              : // static tree
    4101              : // build_constexpr_constructor_member_initializers (tree type, tree body)
    4102              : //{
    4103              : //  vec<constructor_elt, va_gc> *vec = NULL;
    4104              : //  bool ok = true;
    4105              : //  while (true)
    4106              : //    switch (TREE_CODE (body))
    4107              : //      {
    4108              : //      case STATEMENT_LIST:
    4109              : //      for (tree stmt : tsi_range (body))
    4110              : //        {
    4111              : //          body = stmt;
    4112              : //          if (TREE_CODE (body) == BIND_EXPR)
    4113              : //            break;
    4114              : //        }
    4115              : //      break;
    4116              : //
    4117              : //      case BIND_EXPR:
    4118              : //      body = BIND_EXPR_BODY (body);
    4119              : //      goto found;
    4120              : //
    4121              : //      default:
    4122              : //      rust_unreachable ();
    4123              : //      }
    4124              : // found:
    4125              : //
    4126              : //  if (TREE_CODE (body) == CLEANUP_POINT_EXPR)
    4127              : //    {
    4128              : //      body = TREE_OPERAND (body, 0);
    4129              : //      if (TREE_CODE (body) == EXPR_STMT)
    4130              : //      body = TREE_OPERAND (body, 0);
    4131              : //      if (TREE_CODE (body) == INIT_EXPR
    4132              : //        && (same_type_ignoring_top_level_qualifiers_p (
    4133              : //          TREE_TYPE (TREE_OPERAND (body, 0)), current_class_type)))
    4134              : //      {
    4135              : //        /* Trivial copy.  */
    4136              : //        return TREE_OPERAND (body, 1);
    4137              : //      }
    4138              : //      ok = build_data_member_initialization (body, &vec);
    4139              : //    }
    4140              : //  else if (TREE_CODE (body) == STATEMENT_LIST)
    4141              : //    {
    4142              : //      for (tree stmt : tsi_range (body))
    4143              : //      {
    4144              : //        ok = build_data_member_initialization (stmt, &vec);
    4145              : //        if (!ok)
    4146              : //          break;
    4147              : //      }
    4148              : //    }
    4149              : //  else if (EXPR_P (body))
    4150              : //    ok = build_data_member_initialization (body, &vec);
    4151              : //  else
    4152              : //    gcc_assert (errorcount > 0);
    4153              : //  if (ok)
    4154              : //    {
    4155              : //      if (vec_safe_length (vec) > 0)
    4156              : //      {
    4157              : //        /* In a delegating constructor, return the target.  */
    4158              : //        constructor_elt *ce = &(*vec)[0];
    4159              : //        if (ce->index == current_class_ptr)
    4160              : //          {
    4161              : //            body = ce->value;
    4162              : //            vec_free (vec);
    4163              : //            return body;
    4164              : //          }
    4165              : //      }
    4166              : //      vec = sort_constexpr_mem_initializers (type, vec);
    4167              : //      return build_constructor (type, vec);
    4168              : //    }
    4169              : //  else
    4170              : //    return error_mark_node;
    4171              : //}
    4172              : 
    4173              : // Subroutine of check_constexpr_fundef.  BODY is the body of a function
    4174              : // declared to be constexpr, or a sub-statement thereof.  Returns the
    4175              : // return value if suitable, error_mark_node for a statement not allowed in
    4176              : // a constexpr function, or NULL_TREE if no return value was found.
    4177              : static tree
    4178            0 : constexpr_fn_retval (const constexpr_ctx *ctx, tree body)
    4179              : {
    4180            0 :   switch (TREE_CODE (body))
    4181              :     {
    4182            0 :     case STATEMENT_LIST:
    4183            0 :       {
    4184            0 :         tree expr = NULL_TREE;
    4185            0 :         for (tree stmt : tsi_range (body))
    4186              :           {
    4187            0 :             tree s = constexpr_fn_retval (ctx, stmt);
    4188            0 :             if (s == error_mark_node)
    4189              :               return error_mark_node;
    4190            0 :             else if (s == NULL_TREE)
    4191              :               /* Keep iterating.  */;
    4192            0 :             else if (expr)
    4193              :               /* Multiple return statements.  */
    4194              :               return error_mark_node;
    4195              :             else
    4196              :               expr = s;
    4197              :           }
    4198              :         return expr;
    4199              :       }
    4200              : 
    4201            0 :     case RETURN_EXPR:
    4202            0 :       {
    4203            0 :         bool non_constant_p = false;
    4204            0 :         bool overflow_p = false;
    4205            0 :         return eval_constant_expression (ctx, body, false, &non_constant_p,
    4206              :                                          &overflow_p, NULL);
    4207              :       }
    4208            0 :     case DECL_EXPR:
    4209            0 :       {
    4210            0 :         tree decl = DECL_EXPR_DECL (body);
    4211            0 :         if (TREE_CODE (decl) == USING_DECL
    4212              :             /* Accept __func__, __FUNCTION__, and __PRETTY_FUNCTION__.  */
    4213            0 :             || DECL_ARTIFICIAL (decl))
    4214              :           return NULL_TREE;
    4215            0 :         return error_mark_node;
    4216              :       }
    4217              : 
    4218            0 :     case CLEANUP_POINT_EXPR:
    4219            0 :       return constexpr_fn_retval (ctx, TREE_OPERAND (body, 0));
    4220              : 
    4221            0 :     case BIND_EXPR:
    4222            0 :       {
    4223            0 :         tree b = BIND_EXPR_BODY (body);
    4224            0 :         return constexpr_fn_retval (ctx, b);
    4225              :       }
    4226            0 :       break;
    4227              : 
    4228            0 :     default:
    4229            0 :       return error_mark_node;
    4230              :     }
    4231              :   return error_mark_node;
    4232              : }
    4233              : 
    4234              : // Taken from cp/constexpr.cc
    4235              : //
    4236              : // If DECL is a scalar enumeration constant or variable with a
    4237              : // constant initializer, return the initializer (or, its initializers,
    4238              : // recursively); otherwise, return DECL.  If STRICT_P, the
    4239              : // initializer is only returned if DECL is a
    4240              : // constant-expression.  If RETURN_AGGREGATE_CST_OK_P, it is ok to
    4241              : // return an aggregate constant.  If UNSHARE_P, return an unshared
    4242              : // copy of the initializer.
    4243              : static tree
    4244         1464 : constant_value_1 (tree decl, bool, bool, bool unshare_p)
    4245              : {
    4246         2926 :   while (TREE_CODE (decl) == CONST_DECL)
    4247              :     {
    4248         1462 :       tree init;
    4249              :       /* If DECL is a static data member in a template
    4250              :          specialization, we must instantiate it here.  The
    4251              :          initializer for the static data member is not processed
    4252              :          until needed; we need it now.  */
    4253              : 
    4254         1462 :       init = DECL_INITIAL (decl);
    4255         1462 :       if (init == error_mark_node)
    4256              :         {
    4257              :           if (TREE_CODE (decl) == CONST_DECL)
    4258              :             /* Treat the error as a constant to avoid cascading errors on
    4259              :                excessively recursive template instantiation (c++/9335).  */
    4260              :             return init;
    4261              :           else
    4262              :             return decl;
    4263              :         }
    4264              : 
    4265              :       decl = init;
    4266              :     }
    4267         1464 :   return unshare_p ? unshare_expr (decl) : decl;
    4268              : }
    4269              : 
    4270              : /* Like scalar_constant_value, but can also return aggregate initializers.
    4271              :  If UNSHARE_P, return an unshared copy of the initializer.  */
    4272              : 
    4273              : tree
    4274         1464 : decl_really_constant_value (tree decl, bool unshare_p /*= true*/)
    4275              : {
    4276         1464 :   return constant_value_1 (decl, /*strict_p=*/true,
    4277              :                            /*return_aggregate_cst_ok_p=*/true,
    4278            0 :                            /*unshare_p=*/unshare_p);
    4279              : }
    4280              : 
    4281              : // A more relaxed version of decl_really_constant_value, used by the
    4282              : // common C/C++ code.
    4283              : tree
    4284            0 : decl_constant_value (tree decl, bool unshare_p)
    4285              : {
    4286            0 :   return constant_value_1 (decl, /*strict_p=*/false,
    4287              :                            /*return_aggregate_cst_ok_p=*/true,
    4288            0 :                            /*unshare_p=*/unshare_p);
    4289              : }
    4290              : 
    4291              : static void
    4292            2 : non_const_var_error (location_t loc, tree r)
    4293              : {
    4294            2 :   tree type = TREE_TYPE (r);
    4295              : 
    4296              :   /* Avoid error cascade.  */
    4297            2 :   if (DECL_INITIAL (r) == error_mark_node)
    4298              :     return;
    4299            2 :   if (DECL_DECLARED_CONSTEXPR_P (r))
    4300            0 :     inform (DECL_SOURCE_LOCATION (r), "%qD used in its own initializer", r);
    4301            2 :   else if (INTEGRAL_OR_ENUMERATION_TYPE_P (type))
    4302              :     {
    4303            2 :       if (!DECL_INITIAL (r) || !TREE_CONSTANT (DECL_INITIAL (r))
    4304            2 :           || !DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (r))
    4305            2 :         inform (DECL_SOURCE_LOCATION (r),
    4306              :                 "%qD was not initialized with a constant "
    4307              :                 "expression",
    4308              :                 r);
    4309              :       else
    4310            0 :         gcc_unreachable ();
    4311              :     }
    4312            0 :   else if (TYPE_REF_P (type))
    4313            0 :     inform (DECL_SOURCE_LOCATION (r),
    4314              :             "%qD was not initialized with a constant "
    4315              :             "expression",
    4316              :             r);
    4317              :   else
    4318              :     {
    4319            0 :       if (!DECL_DECLARED_CONSTEXPR_P (r))
    4320            0 :         inform (DECL_SOURCE_LOCATION (r), "%qD was not declared %<constexpr%>",
    4321              :                 r);
    4322              :       else
    4323            0 :         inform (DECL_SOURCE_LOCATION (r),
    4324              :                 "%qD does not have integral or enumeration type", r);
    4325              :     }
    4326              : }
    4327              : 
    4328              : static tree
    4329         2408 : get_callee (tree call)
    4330              : {
    4331         2408 :   if (call == NULL_TREE)
    4332              :     return call;
    4333         2408 :   else if (TREE_CODE (call) == CALL_EXPR)
    4334         2408 :     return CALL_EXPR_FN (call);
    4335              : 
    4336              :   return NULL_TREE;
    4337              : }
    4338              : 
    4339              : // We have an expression tree T that represents a call, either CALL_EXPR
    4340              : // or AGGR_INIT_EXPR. If the call is lexically to a named function,
    4341              : // return the _DECL for that function.
    4342              : static tree
    4343         2408 : get_function_named_in_call (tree t)
    4344              : {
    4345         2408 :   tree fun = get_callee (t);
    4346         2408 :   if (fun && TREE_CODE (fun) == ADDR_EXPR
    4347         2866 :       && TREE_CODE (TREE_OPERAND (fun, 0)) == FUNCTION_DECL)
    4348          458 :     fun = TREE_OPERAND (fun, 0);
    4349         2408 :   return fun;
    4350              : }
    4351              : 
    4352              : // forked from gcc/cp/constexpr.cc maybe_constexpr_fn
    4353              : 
    4354              : /* True if a function might be declared constexpr  */
    4355              : 
    4356              : bool
    4357            0 : maybe_constexpr_fn (tree t)
    4358              : {
    4359            0 :   return (DECL_DECLARED_CONSTEXPR_P (t));
    4360              : }
    4361              : 
    4362              : // forked from gcc/cp/constexpr.cc var_in_maybe_constexpr_fn
    4363              : 
    4364              : /* True if T was declared in a function that might be constexpr: either a
    4365              :    function that was declared constexpr.  */
    4366              : 
    4367              : bool
    4368            0 : var_in_maybe_constexpr_fn (tree t)
    4369              : {
    4370            0 :   return (DECL_FUNCTION_SCOPE_P (t) && maybe_constexpr_fn (DECL_CONTEXT (t)));
    4371              : }
    4372              : 
    4373              : /* P0859: A function is needed for constant evaluation if it is a constexpr
    4374              :    function that is named by an expression ([basic.def.odr]) that is
    4375              :    potentially constant evaluated.
    4376              : 
    4377              :    So we need to instantiate any constexpr functions mentioned by the
    4378              :    expression even if the definition isn't needed for evaluating the
    4379              :    expression.  */
    4380              : 
    4381              : static tree
    4382            0 : instantiate_cx_fn_r (tree *tp, int *walk_subtrees, void * /*data*/)
    4383              : {
    4384            0 :   if (TREE_CODE (*tp) == CALL_EXPR)
    4385              :     {
    4386            0 :       if (EXPR_HAS_LOCATION (*tp))
    4387            0 :         input_location = EXPR_LOCATION (*tp);
    4388              :     }
    4389              : 
    4390            0 :   if (!EXPR_P (*tp))
    4391            0 :     *walk_subtrees = 0;
    4392              : 
    4393            0 :   return NULL_TREE;
    4394              : }
    4395              : 
    4396              : static void
    4397            0 : instantiate_constexpr_fns (tree t)
    4398              : {
    4399            0 :   location_t loc = input_location;
    4400            0 :   rs_walk_tree_without_duplicates (&t, instantiate_cx_fn_r, NULL);
    4401            0 :   input_location = loc;
    4402            0 : }
    4403              : 
    4404              : /* Returns less than, equal to, or greater than zero if KEY is found to be
    4405              :    less than, to match, or to be greater than the constructor_elt's INDEX.  */
    4406              : 
    4407              : static int
    4408            0 : array_index_cmp (tree key, tree index)
    4409              : {
    4410            0 :   gcc_assert (TREE_CODE (key) == INTEGER_CST);
    4411              : 
    4412            0 :   switch (TREE_CODE (index))
    4413              :     {
    4414            0 :     case INTEGER_CST:
    4415            0 :       return tree_int_cst_compare (key, index);
    4416            0 :     case RANGE_EXPR:
    4417            0 :       {
    4418            0 :         tree lo = TREE_OPERAND (index, 0);
    4419            0 :         tree hi = TREE_OPERAND (index, 1);
    4420            0 :         if (tree_int_cst_lt (key, lo))
    4421              :           return -1;
    4422            0 :         else if (tree_int_cst_lt (hi, key))
    4423              :           return 1;
    4424              :         else
    4425            0 :           return 0;
    4426              :       }
    4427            0 :     default:
    4428            0 :       rust_unreachable ();
    4429              :     }
    4430              : }
    4431              : 
    4432              : /* If T is a CONSTRUCTOR, return an unshared copy of T and any
    4433              :    sub-CONSTRUCTORs.  Otherwise return T.
    4434              : 
    4435              :    We use this whenever we initialize an object as a whole, whether it's a
    4436              :    parameter, a local variable, or a subobject, so that subsequent
    4437              :    modifications don't affect other places where it was used.  */
    4438              : 
    4439              : tree
    4440         2545 : unshare_constructor (tree t MEM_STAT_DECL)
    4441              : {
    4442         2545 :   if (!t || TREE_CODE (t) != CONSTRUCTOR)
    4443              :     return t;
    4444           81 :   auto_vec<tree *, 4> ptrs;
    4445           81 :   ptrs.safe_push (&t);
    4446           81 :   while (!ptrs.is_empty ())
    4447              :     {
    4448           88 :       tree *p = ptrs.pop ();
    4449           88 :       tree n = copy_node (*p PASS_MEM_STAT);
    4450          176 :       CONSTRUCTOR_ELTS (n)
    4451          162 :         = vec_safe_copy (CONSTRUCTOR_ELTS (*p) PASS_MEM_STAT);
    4452           88 :       *p = n;
    4453           88 :       vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (n);
    4454           88 :       constructor_elt *ce;
    4455          673 :       for (HOST_WIDE_INT i = 0; vec_safe_iterate (v, i, &ce); ++i)
    4456          416 :         if (ce->value && TREE_CODE (ce->value) == CONSTRUCTOR)
    4457            7 :           ptrs.safe_push (&ce->value);
    4458              :     }
    4459           81 :   return t;
    4460           81 : }
    4461              : 
    4462              : /* Returns the index of the constructor_elt of ARY which matches DINDEX, or -1
    4463              :    if none.  If INSERT is true, insert a matching element rather than fail. */
    4464              : 
    4465              : static HOST_WIDE_INT
    4466           10 : find_array_ctor_elt (tree ary, tree dindex, bool insert)
    4467              : {
    4468           10 :   if (tree_int_cst_sgn (dindex) < 0)
    4469              :     return -1;
    4470              : 
    4471           10 :   unsigned HOST_WIDE_INT i = tree_to_uhwi (dindex);
    4472           10 :   vec<constructor_elt, va_gc> *elts = CONSTRUCTOR_ELTS (ary);
    4473           10 :   unsigned HOST_WIDE_INT len = vec_safe_length (elts);
    4474              : 
    4475           11 :   unsigned HOST_WIDE_INT end = len;
    4476           10 :   unsigned HOST_WIDE_INT begin = 0;
    4477              : 
    4478              :   /* If the last element of the CONSTRUCTOR has its own index, we can assume
    4479              :      that the same is true of the other elements and index directly.  */
    4480           10 :   if (end > 0)
    4481              :     {
    4482            9 :       tree cindex = (*elts)[end - 1].index;
    4483            9 :       if (cindex == NULL_TREE)
    4484              :         {
    4485              :           /* Verify that if the last index is missing, all indexes
    4486              :              are missing.  */
    4487            0 :           if (flag_checking)
    4488            0 :             for (unsigned int j = 0; j < len - 1; ++j)
    4489            0 :               gcc_assert ((*elts)[j].index == NULL_TREE);
    4490            0 :           if (i < end)
    4491            0 :             return i;
    4492              :           else
    4493              :             {
    4494            0 :               begin = end;
    4495            0 :               if (i == end)
    4496              :                 /* If the element is to be added right at the end,
    4497              :                    make sure it is added with cleared index too.  */
    4498            1 :                 dindex = NULL_TREE;
    4499            0 :               else if (insert)
    4500              :                 /* Otherwise, in order not to break the assumption
    4501              :                    that CONSTRUCTOR either has all indexes or none,
    4502              :                    we need to add indexes to all elements.  */
    4503            0 :                 for (unsigned int j = 0; j < len; ++j)
    4504            0 :                   (*elts)[j].index = build_int_cst (TREE_TYPE (dindex), j);
    4505              :             }
    4506              :         }
    4507            9 :       else if (TREE_CODE (cindex) == INTEGER_CST
    4508            9 :                && compare_tree_int (cindex, end - 1) == 0)
    4509              :         {
    4510            9 :           if (i < end)
    4511            9 :             return i;
    4512              :           else
    4513            1 :             begin = end;
    4514              :         }
    4515              :     }
    4516              : 
    4517              :   /* Otherwise, find a matching index by means of a binary search.  */
    4518            1 :   while (begin != end)
    4519              :     {
    4520            0 :       unsigned HOST_WIDE_INT middle = (begin + end) / 2;
    4521            0 :       constructor_elt &elt = (*elts)[middle];
    4522            0 :       tree idx = elt.index;
    4523              : 
    4524            0 :       int cmp = array_index_cmp (dindex, idx);
    4525            0 :       if (cmp < 0)
    4526              :         end = middle;
    4527            0 :       else if (cmp > 0)
    4528            0 :         begin = middle + 1;
    4529              :       else
    4530              :         {
    4531            0 :           if (insert && TREE_CODE (idx) == RANGE_EXPR)
    4532              :             {
    4533              :               /* We need to split the range.  */
    4534            0 :               constructor_elt e;
    4535            0 :               tree lo = TREE_OPERAND (idx, 0);
    4536            0 :               tree hi = TREE_OPERAND (idx, 1);
    4537            0 :               tree value = elt.value;
    4538            0 :               dindex = fold_convert (sizetype, dindex);
    4539            0 :               if (tree_int_cst_lt (lo, dindex))
    4540              :                 {
    4541              :                   /* There are still some lower elts; shorten the range.  */
    4542            0 :                   tree new_hi
    4543            0 :                     = int_const_binop (MINUS_EXPR, dindex, size_one_node);
    4544            0 :                   if (tree_int_cst_equal (lo, new_hi))
    4545              :                     /* Only one element left, no longer a range.  */
    4546            0 :                     elt.index = lo;
    4547              :                   else
    4548            0 :                     TREE_OPERAND (idx, 1) = new_hi;
    4549              :                   /* Append the element we want to insert.  */
    4550            0 :                   ++middle;
    4551            0 :                   e.index = dindex;
    4552            0 :                   e.value = unshare_constructor (value);
    4553            0 :                   vec_safe_insert (CONSTRUCTOR_ELTS (ary), middle, e);
    4554              :                 }
    4555              :               else
    4556              :                 /* No lower elts, the range elt is now ours.  */
    4557            0 :                 elt.index = dindex;
    4558              : 
    4559            0 :               if (tree_int_cst_lt (dindex, hi))
    4560              :                 {
    4561              :                   /* There are still some higher elts; append a range.  */
    4562            0 :                   tree new_lo
    4563            0 :                     = int_const_binop (PLUS_EXPR, dindex, size_one_node);
    4564            0 :                   if (tree_int_cst_equal (new_lo, hi))
    4565              :                     e.index = hi;
    4566              :                   else
    4567            0 :                     e.index = build2 (RANGE_EXPR, sizetype, new_lo, hi);
    4568            0 :                   e.value = unshare_constructor (value);
    4569            0 :                   vec_safe_insert (CONSTRUCTOR_ELTS (ary), middle + 1, e);
    4570              :                 }
    4571              :             }
    4572            0 :           return middle;
    4573              :         }
    4574              :     }
    4575              : 
    4576            1 :   if (insert)
    4577              :     {
    4578            1 :       constructor_elt e = {dindex, NULL_TREE};
    4579            1 :       vec_safe_insert (CONSTRUCTOR_ELTS (ary), end, e);
    4580            1 :       return end;
    4581              :     }
    4582              : 
    4583              :   return -1;
    4584              : }
    4585              : 
    4586              : /* Some expressions may have constant operands but are not constant
    4587              :    themselves, such as 1/0.  Call this function to check for that
    4588              :    condition.
    4589              : 
    4590              :    We only call this in places that require an arithmetic constant, not in
    4591              :    places where we might have a non-constant expression that can be a
    4592              :    component of a constant expression, such as the address of a constexpr
    4593              :    variable that might be dereferenced later.  */
    4594              : 
    4595              : static bool
    4596       262562 : verify_constant (tree t, bool allow_non_constant, bool *non_constant_p,
    4597              :                  bool *overflow_p)
    4598              : {
    4599       262562 :   if (!*non_constant_p && !reduced_constant_expression_p (t) && t != void_node)
    4600              :     {
    4601            2 :       if (!allow_non_constant)
    4602            2 :         error_at (EXPR_LOCATION (t), "is not a constant expression");
    4603            2 :       *non_constant_p = true;
    4604              :     }
    4605       262562 :   if (TREE_OVERFLOW_P (t))
    4606              :     {
    4607            0 :       if (!allow_non_constant)
    4608              :         {
    4609            0 :           permerror (input_location, "overflow in constant expression");
    4610              :           /* If we're being permissive (and are in an enforcing
    4611              :              context), ignore the overflow.  */
    4612            0 :           if (flag_permissive)
    4613            0 :             return *non_constant_p;
    4614              :         }
    4615            0 :       *overflow_p = true;
    4616              :     }
    4617       262562 :   return *non_constant_p;
    4618              : }
    4619              : 
    4620              : // forked from gcc/cp/constexpr.cc find_heap_var_refs
    4621              : 
    4622              : /* Look for heap variables in the expression *TP.  */
    4623              : 
    4624              : static tree
    4625            0 : find_heap_var_refs (tree *tp, int *walk_subtrees, void * /*data*/)
    4626              : {
    4627            0 :   if (VAR_P (*tp)
    4628            0 :       && (DECL_NAME (*tp) == heap_uninit_identifier
    4629            0 :           || DECL_NAME (*tp) == heap_identifier
    4630            0 :           || DECL_NAME (*tp) == heap_vec_uninit_identifier
    4631            0 :           || DECL_NAME (*tp) == heap_vec_identifier
    4632            0 :           || DECL_NAME (*tp) == heap_deleted_identifier))
    4633              :     return *tp;
    4634              : 
    4635            0 :   if (TYPE_P (*tp))
    4636            0 :     *walk_subtrees = 0;
    4637              :   return NULL_TREE;
    4638              : }
    4639              : 
    4640              : // forked from gcc/cp/constexpr.cc find_immediate_fndecl
    4641              : 
    4642              : /* Find immediate function decls in *TP if any.  */
    4643              : 
    4644              : static tree
    4645            0 : find_immediate_fndecl (tree *tp, int * /*walk_subtrees*/, void * /*data*/)
    4646              : {
    4647            0 :   if (TREE_CODE (*tp) == FUNCTION_DECL && DECL_IMMEDIATE_FUNCTION_P (*tp))
    4648              :     return *tp;
    4649            0 :   if (TREE_CODE (*tp) == PTRMEM_CST
    4650            0 :       && TREE_CODE (PTRMEM_CST_MEMBER (*tp)) == FUNCTION_DECL
    4651            0 :       && DECL_IMMEDIATE_FUNCTION_P (PTRMEM_CST_MEMBER (*tp)))
    4652              :     return PTRMEM_CST_MEMBER (*tp);
    4653              :   return NULL_TREE;
    4654              : }
    4655              : 
    4656              : // forked in gcc/cp/constexpr.cc diag_array_subscript
    4657              : 
    4658              : /* Under the control of CTX, issue a detailed diagnostic for
    4659              :    an out-of-bounds subscript INDEX into the expression ARRAY.  */
    4660              : 
    4661              : static void
    4662            1 : diag_array_subscript (location_t loc, const constexpr_ctx *ctx, tree array,
    4663              :                       tree index)
    4664              : {
    4665            1 :   if (!ctx->quiet)
    4666              :     {
    4667            1 :       tree arraytype = TREE_TYPE (array);
    4668              : 
    4669              :       /* Convert the unsigned array subscript to a signed integer to avoid
    4670              :          printing huge numbers for small negative values.  */
    4671            1 :       tree sidx = fold_convert (ssizetype, index);
    4672            1 :       STRIP_ANY_LOCATION_WRAPPER (array);
    4673            1 :       if (DECL_P (array))
    4674              :         {
    4675            1 :           if (TYPE_DOMAIN (arraytype))
    4676            1 :             error_at (loc,
    4677              :                       "array subscript value %qE is outside the bounds "
    4678              :                       "of array %qD of type %qT",
    4679              :                       sidx, array, arraytype);
    4680              :           else
    4681            0 :             error_at (loc,
    4682              :                       "nonzero array subscript %qE is used with array %qD of "
    4683              :                       "type %qT with unknown bounds",
    4684              :                       sidx, array, arraytype);
    4685            1 :           inform (DECL_SOURCE_LOCATION (array), "declared here");
    4686              :         }
    4687            0 :       else if (TYPE_DOMAIN (arraytype))
    4688            0 :         error_at (loc,
    4689              :                   "array subscript value %qE is outside the bounds "
    4690              :                   "of array type %qT",
    4691              :                   sidx, arraytype);
    4692              :       else
    4693            0 :         error_at (loc,
    4694              :                   "nonzero array subscript %qE is used with array of type %qT "
    4695              :                   "with unknown bounds",
    4696              :                   sidx, arraytype);
    4697              :     }
    4698            1 : }
    4699              : 
    4700              : // forked from gcc/cp/constexpr.cc get_array_or_vector_nelts
    4701              : 
    4702              : /* Return the number of elements for TYPE (which is an ARRAY_TYPE or
    4703              :    a VECTOR_TYPE).  */
    4704              : 
    4705              : static tree
    4706           10 : get_array_or_vector_nelts (const constexpr_ctx *ctx, tree type,
    4707              :                            bool *non_constant_p, bool *overflow_p,
    4708              :                            tree *jump_target)
    4709              : {
    4710           10 :   tree nelts;
    4711           10 :   if (TREE_CODE (type) == ARRAY_TYPE)
    4712              :     {
    4713           10 :       if (TYPE_DOMAIN (type))
    4714           10 :         nelts = array_type_nelts_top (type);
    4715              :       else
    4716            0 :         nelts = size_zero_node;
    4717              :     }
    4718            0 :   else if (VECTOR_TYPE_P (type))
    4719            0 :     nelts = size_int (TYPE_VECTOR_SUBPARTS (type));
    4720              :   else
    4721            0 :     rust_unreachable ();
    4722              : 
    4723              :   /* For VLAs, the number of elements won't be an integer constant.  */
    4724           10 :   nelts = eval_constant_expression (ctx, nelts, false, non_constant_p,
    4725              :                                     overflow_p, jump_target);
    4726           10 :   return nelts;
    4727              : }
    4728              : 
    4729              : // forked from gcc/cp/constexpr.cc eval_and_check_array_index
    4730              : 
    4731              : /* Subroutine of cxx_eval_array_reference.  T is an ARRAY_REF; evaluate the
    4732              :    subscript, diagnose any problems with it, and return the result.  */
    4733              : 
    4734              : static tree
    4735           10 : eval_and_check_array_index (const constexpr_ctx *ctx, tree t,
    4736              :                             bool allow_one_past, bool *non_constant_p,
    4737              :                             bool *overflow_p, tree *jump_target)
    4738              : {
    4739           10 :   location_t loc = rs_expr_loc_or_input_loc (t);
    4740           10 :   tree ary = TREE_OPERAND (t, 0);
    4741           10 :   t = TREE_OPERAND (t, 1);
    4742           10 :   tree index = eval_constant_expression (ctx, t, allow_one_past, non_constant_p,
    4743              :                                          overflow_p, jump_target);
    4744           10 :   VERIFY_CONSTANT (index);
    4745              : 
    4746           10 :   if (!tree_fits_shwi_p (index) || tree_int_cst_sgn (index) < 0)
    4747              :     {
    4748            0 :       diag_array_subscript (loc, ctx, ary, index);
    4749            0 :       *non_constant_p = true;
    4750            0 :       return t;
    4751              :     }
    4752              : 
    4753           10 :   tree nelts = get_array_or_vector_nelts (ctx, TREE_TYPE (ary), non_constant_p,
    4754              :                                           overflow_p, jump_target);
    4755           10 :   VERIFY_CONSTANT (nelts);
    4756           20 :   if (allow_one_past ? !tree_int_cst_le (index, nelts)
    4757           10 :                      : !tree_int_cst_lt (index, nelts))
    4758              :     {
    4759            1 :       diag_array_subscript (loc, ctx, ary, index);
    4760            1 :       *non_constant_p = true;
    4761            1 :       return t;
    4762              :     }
    4763              : 
    4764              :   return index;
    4765              : }
    4766              : 
    4767              : // forked from gcc/cp/constexpr.cc extract_string_elt
    4768              : 
    4769              : /* Extract element INDEX consisting of CHARS_PER_ELT chars from
    4770              :    STRING_CST STRING.  */
    4771              : 
    4772              : static tree
    4773            0 : extract_string_elt (tree string, unsigned chars_per_elt, unsigned index)
    4774              : {
    4775            0 :   tree type = cv_unqualified (TREE_TYPE (TREE_TYPE (string)));
    4776            0 :   tree r;
    4777              : 
    4778            0 :   if (chars_per_elt == 1)
    4779            0 :     r = build_int_cst (type, TREE_STRING_POINTER (string)[index]);
    4780              :   else
    4781              :     {
    4782            0 :       const unsigned char *ptr
    4783            0 :         = ((const unsigned char *) TREE_STRING_POINTER (string)
    4784            0 :            + index * chars_per_elt);
    4785            0 :       r = native_interpret_expr (type, ptr, chars_per_elt);
    4786              :     }
    4787            0 :   return r;
    4788              : }
    4789              : 
    4790              : /* Check whether the parameter and return types of FUN are valid for a
    4791              :    constexpr function, and complain if COMPLAIN.  */
    4792              : 
    4793              : bool
    4794            0 : is_valid_constexpr_fn (tree fun, bool complain)
    4795              : {
    4796            0 :   bool ret = true;
    4797              : 
    4798            0 :   for (tree parm = FUNCTION_FIRST_USER_PARM (fun); parm != NULL_TREE;
    4799            0 :        parm = TREE_CHAIN (parm))
    4800            0 :     if (!literal_type_p (TREE_TYPE (parm)))
    4801              :       {
    4802            0 :         ret = false;
    4803            0 :         if (complain)
    4804              :           {
    4805              :             // auto_diagnostic_group d;
    4806              :             // error ("invalid type for parameter %d of %<constexpr%> "
    4807              :             //        "function %q+#D",
    4808              :             //        DECL_PARM_INDEX (parm), fun);
    4809            0 :             location_t locus = DECL_SOURCE_LOCATION (fun);
    4810            0 :             rust_error_at (
    4811              :               locus, "invalid type for parameter %d of %<constexpr%> function",
    4812            0 :               DECL_PARM_INDEX (parm));
    4813              :           }
    4814              :       }
    4815              : 
    4816            0 :   return ret;
    4817              : }
    4818              : 
    4819              : void
    4820            0 : explain_invalid_constexpr_fn (tree fun)
    4821              : {
    4822            0 :   static hash_set<tree> *diagnosed;
    4823              :   // tree body;
    4824              : 
    4825            0 :   if (diagnosed == NULL)
    4826            0 :     diagnosed = new hash_set<tree>;
    4827            0 :   if (diagnosed->add (fun))
    4828              :     /* Already explained.  */
    4829            0 :     return;
    4830              : 
    4831            0 :   iloc_sentinel ils = input_location;
    4832              :   // if (!lambda_static_thunk_p (fun))
    4833              :   //   {
    4834              :   //     /* Diagnostics should completely ignore the static thunk, so leave
    4835              :   //        input_location set to our caller's location.  */
    4836              :   //     input_location = DECL_SOURCE_LOCATION (fun);
    4837              :   //     inform (input_location,
    4838              :   //             "%qD is not usable as a %<constexpr%> function because:",
    4839              :   //             fun);
    4840              :   //   }
    4841              : 
    4842              :   /* First check the declaration.  */
    4843            0 :   if (is_valid_constexpr_fn (fun, true))
    4844              :     {
    4845              :       // /* Then if it's OK, the body.  */
    4846              :       // if (!DECL_DECLARED_CONSTEXPR_P (fun))
    4847              :       //   explain_implicit_non_constexpr (fun);
    4848              :       // else
    4849              :       //   {
    4850              :       //     if (constexpr_fundef *fd = retrieve_constexpr_fundef (fun))
    4851              :       //       body = fd->body;
    4852              :       //     else
    4853              :       //       body = DECL_SAVED_TREE (fun);
    4854              :       //     body = massage_constexpr_body (fun, body);
    4855              :       //     require_potential_rvalue_constant_expression (body);
    4856              :       //   }
    4857              :     }
    4858            0 : }
    4859              : 
    4860              : /* BODY is a validated and massaged definition of a constexpr
    4861              :    function.  Register it in the hash table.  */
    4862              : 
    4863              : void
    4864         6084 : register_constexpr_fundef (const rust_constexpr_fundef &value)
    4865              : {
    4866              :   /* Create the constexpr function table if necessary.  */
    4867         6084 :   if (constexpr_fundef_table == NULL)
    4868          962 :     constexpr_fundef_table
    4869          962 :       = hash_table<rust_constexpr_fundef_hasher>::create_ggc (101);
    4870              : 
    4871        12168 :   rust_constexpr_fundef **slot = constexpr_fundef_table->find_slot (
    4872         6084 :     const_cast<rust_constexpr_fundef *> (&value), INSERT);
    4873              : 
    4874         6084 :   gcc_assert (*slot == NULL);
    4875         6084 :   *slot = ggc_alloc<rust_constexpr_fundef> ();
    4876         6084 :   **slot = value;
    4877         6084 : }
    4878              : 
    4879              : /* We are processing the definition of the constexpr function FUN.
    4880              :    Check that its body fulfills the apropriate requirements and
    4881              :    enter it in the constexpr function definition table.  */
    4882              : 
    4883              : void
    4884         6084 : maybe_save_constexpr_fundef (tree fun)
    4885              : {
    4886              :   // FIXME
    4887              : 
    4888         6084 :   rust_constexpr_fundef entry = {fun, NULL_TREE, NULL_TREE, NULL_TREE};
    4889         6084 :   bool clear_ctx = false;
    4890         6084 :   if (DECL_RESULT (fun) && DECL_CONTEXT (DECL_RESULT (fun)) == NULL_TREE)
    4891              :     {
    4892            0 :       clear_ctx = true;
    4893            0 :       DECL_CONTEXT (DECL_RESULT (fun)) = fun;
    4894              :     }
    4895         6084 :   tree saved_fn = current_function_decl;
    4896         6084 :   current_function_decl = fun;
    4897         6084 :   entry.body = copy_fn (entry.decl, entry.parms, entry.result);
    4898         6084 :   current_function_decl = saved_fn;
    4899         6084 :   if (clear_ctx)
    4900            0 :     DECL_CONTEXT (DECL_RESULT (entry.decl)) = NULL_TREE;
    4901              : 
    4902         6084 :   register_constexpr_fundef (entry);
    4903         6084 : }
    4904              : 
    4905              : /* Evaluate a STATEMENT_LIST for side-effects.  Handles various jump
    4906              :    semantics, for switch, break, continue, and return.  */
    4907              : 
    4908              : static tree
    4909       264641 : eval_statement_list (const constexpr_ctx *ctx, tree t, bool *non_constant_p,
    4910              :                      bool *overflow_p, tree *jump_target)
    4911              : {
    4912       264641 :   tree local_target;
    4913              :   /* In a statement-expression we want to return the last value.
    4914              :      For empty statement expression return void_node.  */
    4915       264641 :   tree r = void_node;
    4916       264641 :   if (!jump_target)
    4917              :     {
    4918            0 :       local_target = NULL_TREE;
    4919            0 :       jump_target = &local_target;
    4920              :     }
    4921      1053311 :   for (tree stmt : tsi_range (t))
    4922              :     {
    4923              :       /* We've found a continue, so skip everything until we reach
    4924              :          the label its jumping to.  */
    4925       791109 :       if (continues (jump_target))
    4926              :         {
    4927            0 :           if (label_matches (ctx, jump_target, stmt))
    4928              :             /* Found it.  */
    4929            0 :             *jump_target = NULL_TREE;
    4930              :           else
    4931            0 :             continue;
    4932              :         }
    4933       791109 :       if (TREE_CODE (stmt) == DEBUG_BEGIN_STMT)
    4934            0 :         continue;
    4935       791109 :       r = eval_constant_expression (ctx, stmt, false, non_constant_p,
    4936              :                                     overflow_p, jump_target);
    4937       791109 :       if (*non_constant_p)
    4938              :         break;
    4939       791091 :       if (returns (jump_target) || breaks (jump_target))
    4940              :         break;
    4941              :     }
    4942       264641 :   if (*jump_target && jump_target == &local_target)
    4943              :     {
    4944              :       /* We aren't communicating the jump to our caller, so give up.  We don't
    4945              :          need to support evaluation of jumps out of statement-exprs.  */
    4946            0 :       if (!ctx->quiet)
    4947            0 :         error_at (EXPR_LOCATION (r), "statement is not a constant expression");
    4948            0 :       *non_constant_p = true;
    4949              :     }
    4950       264641 :   return r;
    4951              : }
    4952              : 
    4953              : // forked from gcc/cp/constexpr.cc cxx_eval_conditional_expression
    4954              : 
    4955              : /* Subroutine of cxx_eval_constant_expression.
    4956              :    Attempt to evaluate condition expressions.  Dead branches are not
    4957              :    looked into.  */
    4958              : 
    4959              : static tree
    4960           21 : eval_conditional_expression (const constexpr_ctx *ctx, tree t, bool lval,
    4961              :                              bool *non_constant_p, bool *overflow_p,
    4962              :                              tree *jump_target)
    4963              : {
    4964           21 :   tree val = eval_constant_expression (ctx, TREE_OPERAND (t, 0),
    4965              :                                        /*lval*/ false, non_constant_p,
    4966              :                                        overflow_p, jump_target);
    4967           21 :   VERIFY_CONSTANT (val);
    4968           21 :   if (TREE_CODE (t) == IF_STMT && IF_STMT_CONSTEVAL_P (t))
    4969              :     {
    4970              :       /* Evaluate the condition as if it was
    4971              :          if (__builtin_is_constant_evaluated ()), i.e. defer it if not
    4972              :          ctx->manifestly_const_eval (as sometimes we try to constant evaluate
    4973              :          without manifestly_const_eval even expressions or parts thereof which
    4974              :          will later be manifestly const_eval evaluated), otherwise fold it to
    4975              :          true.  */
    4976            0 :       if (ctx->manifestly_const_eval)
    4977            0 :         val = boolean_true_node;
    4978              :       else
    4979              :         {
    4980            0 :           *non_constant_p = true;
    4981            0 :           return t;
    4982              :         }
    4983              :     }
    4984              :   /* Don't VERIFY_CONSTANT the other operands.  */
    4985           21 :   if (integer_zerop (val))
    4986           13 :     val = TREE_OPERAND (t, 2);
    4987              :   else
    4988            8 :     val = TREE_OPERAND (t, 1);
    4989           21 :   if (/*TREE_CODE (t) == IF_STMT && */ !val)
    4990           12 :     val = void_node;
    4991           21 :   return eval_constant_expression (ctx, val, lval, non_constant_p, overflow_p,
    4992           21 :                                    jump_target);
    4993              : }
    4994              : 
    4995              : // forked from gcc/cp/constexpr.cc cxx_eval_bit_field_ref
    4996              : 
    4997              : /* Subroutine of cxx_eval_constant_expression.
    4998              :    Attempt to reduce a field access of a value of class type that is
    4999              :    expressed as a BIT_FIELD_REF.  */
    5000              : 
    5001              : static tree
    5002            0 : eval_bit_field_ref (const constexpr_ctx *ctx, tree t, bool lval,
    5003              :                     bool *non_constant_p, bool *overflow_p, tree *jump_target)
    5004              : {
    5005            0 :   tree orig_whole = TREE_OPERAND (t, 0);
    5006            0 :   tree retval, fldval, utype, mask;
    5007            0 :   bool fld_seen = false;
    5008            0 :   HOST_WIDE_INT istart, isize;
    5009            0 :   tree whole = eval_constant_expression (ctx, orig_whole, lval, non_constant_p,
    5010              :                                          overflow_p, jump_target);
    5011            0 :   tree start, field, value;
    5012            0 :   unsigned HOST_WIDE_INT i;
    5013              : 
    5014            0 :   if (whole == orig_whole)
    5015              :     return t;
    5016              :   /* Don't VERIFY_CONSTANT here; we only want to check that we got a
    5017              :      CONSTRUCTOR.  */
    5018            0 :   if (!*non_constant_p && TREE_CODE (whole) != VECTOR_CST
    5019            0 :       && TREE_CODE (whole) != CONSTRUCTOR)
    5020              :     {
    5021            0 :       if (!ctx->quiet)
    5022            0 :         error ("%qE is not a constant expression", orig_whole);
    5023            0 :       *non_constant_p = true;
    5024              :     }
    5025            0 :   if (*non_constant_p)
    5026              :     return t;
    5027              : 
    5028            0 :   if (TREE_CODE (whole) == VECTOR_CST)
    5029            0 :     return fold_ternary (BIT_FIELD_REF, TREE_TYPE (t), whole,
    5030              :                          TREE_OPERAND (t, 1), TREE_OPERAND (t, 2));
    5031              : 
    5032            0 :   start = TREE_OPERAND (t, 2);
    5033            0 :   istart = tree_to_shwi (start);
    5034            0 :   isize = tree_to_shwi (TREE_OPERAND (t, 1));
    5035            0 :   utype = TREE_TYPE (t);
    5036            0 :   if (!TYPE_UNSIGNED (utype))
    5037            0 :     utype = build_nonstandard_integer_type (TYPE_PRECISION (utype), 1);
    5038            0 :   retval = build_int_cst (utype, 0);
    5039            0 :   FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (whole), i, field, value)
    5040              :     {
    5041            0 :       tree bitpos = bit_position (field);
    5042            0 :       STRIP_ANY_LOCATION_WRAPPER (value);
    5043            0 :       if (bitpos == start && DECL_SIZE (field) == TREE_OPERAND (t, 1))
    5044              :         return value;
    5045            0 :       if (TREE_CODE (TREE_TYPE (field)) == INTEGER_TYPE
    5046            0 :           && TREE_CODE (value) == INTEGER_CST && tree_fits_shwi_p (bitpos)
    5047            0 :           && tree_fits_shwi_p (DECL_SIZE (field)))
    5048              :         {
    5049            0 :           HOST_WIDE_INT bit = tree_to_shwi (bitpos);
    5050            0 :           HOST_WIDE_INT sz = tree_to_shwi (DECL_SIZE (field));
    5051            0 :           HOST_WIDE_INT shift;
    5052            0 :           if (bit >= istart && bit + sz <= istart + isize)
    5053              :             {
    5054            0 :               fldval = fold_convert (utype, value);
    5055            0 :               mask = build_int_cst_type (utype, -1);
    5056            0 :               mask = fold_build2 (LSHIFT_EXPR, utype, mask,
    5057              :                                   size_int (TYPE_PRECISION (utype) - sz));
    5058            0 :               mask = fold_build2 (RSHIFT_EXPR, utype, mask,
    5059              :                                   size_int (TYPE_PRECISION (utype) - sz));
    5060            0 :               fldval = fold_build2 (BIT_AND_EXPR, utype, fldval, mask);
    5061            0 :               shift = bit - istart;
    5062            0 :               if (BYTES_BIG_ENDIAN)
    5063              :                 shift = TYPE_PRECISION (utype) - shift - sz;
    5064            0 :               fldval
    5065            0 :                 = fold_build2 (LSHIFT_EXPR, utype, fldval, size_int (shift));
    5066            0 :               retval = fold_build2 (BIT_IOR_EXPR, utype, retval, fldval);
    5067            0 :               fld_seen = true;
    5068              :             }
    5069              :         }
    5070              :     }
    5071            0 :   if (fld_seen)
    5072            0 :     return fold_convert (TREE_TYPE (t), retval);
    5073            0 :   rust_unreachable ();
    5074              :   return error_mark_node;
    5075              : }
    5076              : 
    5077              : // forked from gcc/cp/constexpr.cc returns
    5078              : 
    5079              : /* Predicates for the meaning of *jump_target.  */
    5080              : 
    5081              : static bool
    5082      1053256 : returns (tree *jump_target)
    5083              : {
    5084      1053256 :   return *jump_target
    5085      1053256 :          && (TREE_CODE (*jump_target) == RETURN_EXPR
    5086           16 :              || (TREE_CODE (*jump_target) == LABEL_DECL
    5087            9 :                  && LABEL_DECL_CDTOR (*jump_target)));
    5088              : }
    5089              : 
    5090              : // forked from gcc/cp/constexpr.cc breaks
    5091              : 
    5092              : static bool
    5093      1313010 : breaks (tree *jump_target)
    5094              : {
    5095      1313010 :   return *jump_target
    5096      1313010 :          && ((TREE_CODE (*jump_target) == LABEL_DECL
    5097            9 :               && LABEL_DECL_BREAK (*jump_target))
    5098           20 :              || TREE_CODE (*jump_target) == BREAK_STMT
    5099           20 :              || TREE_CODE (*jump_target) == EXIT_EXPR);
    5100              : }
    5101              : 
    5102              : // forked from gcc/cp/constexpr.cc continues
    5103              : 
    5104              : static bool
    5105      1053274 : continues (tree *jump_target)
    5106              : {
    5107      1053274 :   return *jump_target
    5108      1053274 :          && ((TREE_CODE (*jump_target) == LABEL_DECL
    5109            7 :               && LABEL_DECL_CONTINUE (*jump_target))
    5110            7 :              || TREE_CODE (*jump_target) == CONTINUE_STMT);
    5111              : }
    5112              : 
    5113              : // forked from gcc/cp/constexpr.cc switches
    5114              : 
    5115              : static bool
    5116       262163 : switches (tree *jump_target)
    5117              : {
    5118       262163 :   return *jump_target && TREE_CODE (*jump_target) == INTEGER_CST;
    5119              : }
    5120              : 
    5121              : // forked from gcc/cp/constexpr.cc cxx_eval_loop_expr
    5122              : 
    5123              : /* Evaluate a LOOP_EXPR for side-effects.  Handles break and return
    5124              :    semantics; continue semantics are covered by cxx_eval_statement_list.  */
    5125              : 
    5126              : static tree
    5127            5 : eval_loop_expr (const constexpr_ctx *ctx, tree t, bool *non_constant_p,
    5128              :                 bool *overflow_p, tree *jump_target)
    5129              : {
    5130            5 :   constexpr_ctx new_ctx = *ctx;
    5131            5 :   tree local_target;
    5132            5 :   if (!jump_target)
    5133              :     {
    5134            0 :       local_target = NULL_TREE;
    5135            0 :       jump_target = &local_target;
    5136              :     }
    5137              : 
    5138            5 :   tree body, cond = NULL_TREE, expr = NULL_TREE;
    5139            5 :   int count = 0;
    5140            5 :   switch (TREE_CODE (t))
    5141              :     {
    5142            5 :     case LOOP_EXPR:
    5143            5 :       body = LOOP_EXPR_BODY (t);
    5144            5 :       break;
    5145            0 :     case WHILE_STMT:
    5146            0 :       body = WHILE_BODY (t);
    5147            0 :       cond = WHILE_COND (t);
    5148            0 :       count = -1;
    5149            0 :       break;
    5150            0 :     case FOR_STMT:
    5151            0 :       if (FOR_INIT_STMT (t))
    5152            0 :         eval_constant_expression (ctx, FOR_INIT_STMT (t), /*lval*/ false,
    5153              :                                   non_constant_p, overflow_p, jump_target);
    5154            0 :       if (*non_constant_p)
    5155              :         return NULL_TREE;
    5156            0 :       body = FOR_BODY (t);
    5157            0 :       cond = FOR_COND (t);
    5158            0 :       expr = FOR_EXPR (t);
    5159            0 :       count = -1;
    5160            0 :       break;
    5161            0 :     default:
    5162            0 :       rust_unreachable ();
    5163              :     }
    5164           10 :   auto_vec<tree, 10> save_exprs;
    5165            5 :   new_ctx.save_exprs = &save_exprs;
    5166       262168 :   do
    5167              :     {
    5168       262168 :       if (count != -1)
    5169              :         {
    5170       262168 :           if (body)
    5171       262168 :             eval_constant_expression (&new_ctx, body, /*lval*/ false,
    5172              :                                       non_constant_p, overflow_p, jump_target);
    5173       262168 :           if (breaks (jump_target))
    5174              :             {
    5175            4 :               *jump_target = NULL_TREE;
    5176            4 :               break;
    5177              :             }
    5178              : 
    5179       262164 :           if (TREE_CODE (t) != LOOP_EXPR && continues (jump_target))
    5180            0 :             *jump_target = NULL_TREE;
    5181              : 
    5182       262164 :           if (expr)
    5183            0 :             eval_constant_expression (&new_ctx, expr, /*lval*/ false,
    5184              :                                       non_constant_p, overflow_p, jump_target);
    5185              :         }
    5186              : 
    5187       262164 :       if (cond)
    5188              :         {
    5189            0 :           tree res = eval_constant_expression (&new_ctx, cond, /*lval*/ false,
    5190              :                                                non_constant_p, overflow_p,
    5191              :                                                jump_target);
    5192            0 :           if (res)
    5193              :             {
    5194            0 :               if (verify_constant (res, ctx->quiet, non_constant_p, overflow_p))
    5195              :                 break;
    5196            0 :               if (integer_zerop (res))
    5197              :                 break;
    5198              :             }
    5199              :           else
    5200            0 :             gcc_assert (*jump_target);
    5201              :         }
    5202              : 
    5203              :       /* Forget saved values of SAVE_EXPRs and TARGET_EXPRs.  */
    5204       786492 :       for (tree save_expr : save_exprs)
    5205            0 :         ctx->global->values.remove (save_expr);
    5206       262164 :       save_exprs.truncate (0);
    5207              : 
    5208       262164 :       if (++count >= constexpr_loop_limit)
    5209              :         {
    5210            1 :           if (!ctx->quiet)
    5211            2 :             error_at (rs_expr_loc_or_input_loc (t),
    5212              :                       "%<constexpr%> loop iteration count exceeds limit of %d "
    5213              :                       "(use %<-fconstexpr-loop-limit=%> to increase the limit)",
    5214              :                       constexpr_loop_limit);
    5215            1 :           *non_constant_p = true;
    5216            1 :           break;
    5217              :         }
    5218              :     }
    5219       262163 :   while (!returns (jump_target) && !breaks (jump_target)
    5220       262163 :          && !continues (jump_target) && (!switches (jump_target) || count == 0)
    5221       524326 :          && !*non_constant_p);
    5222              : 
    5223              :   /* Forget saved values of SAVE_EXPRs and TARGET_EXPRs.  */
    5224           15 :   for (tree save_expr : save_exprs)
    5225            0 :     ctx->global->values.remove (save_expr);
    5226              : 
    5227            5 :   return NULL_TREE;
    5228              : }
    5229              : 
    5230              : // forked from gcc/cp/constexpr.cc cxx_eval_switch_expr
    5231              : 
    5232              : /* Evaluate a SWITCH_EXPR for side-effects.  Handles switch and break jump
    5233              :    semantics.  */
    5234              : 
    5235              : static tree
    5236            0 : eval_switch_expr (const constexpr_ctx *ctx, tree t, bool *non_constant_p,
    5237              :                   bool *overflow_p, tree *jump_target)
    5238              : {
    5239            0 :   tree cond
    5240            0 :     = TREE_CODE (t) == SWITCH_STMT ? SWITCH_STMT_COND (t) : SWITCH_COND (t);
    5241            0 :   cond = eval_constant_expression (ctx, cond, false, non_constant_p, overflow_p,
    5242              :                                    jump_target);
    5243            0 :   VERIFY_CONSTANT (cond);
    5244            0 :   *jump_target = cond;
    5245              : 
    5246            0 :   tree body
    5247            0 :     = TREE_CODE (t) == SWITCH_STMT ? SWITCH_STMT_BODY (t) : SWITCH_BODY (t);
    5248            0 :   constexpr_ctx new_ctx = *ctx;
    5249            0 :   constexpr_switch_state css = css_default_not_seen;
    5250            0 :   new_ctx.css_state = &css;
    5251            0 :   eval_constant_expression (&new_ctx, body, false, non_constant_p, overflow_p,
    5252              :                             jump_target);
    5253            0 :   if (switches (jump_target) && css == css_default_seen)
    5254              :     {
    5255              :       /* If the SWITCH_EXPR body has default: label, process it once again,
    5256              :          this time instructing label_matches to return true for default:
    5257              :          label on switches (jump_target).  */
    5258            0 :       css = css_default_processing;
    5259            0 :       eval_constant_expression (&new_ctx, body, false, non_constant_p,
    5260              :                                 overflow_p, jump_target);
    5261              :     }
    5262            0 :   if (breaks (jump_target) || switches (jump_target))
    5263            0 :     *jump_target = NULL_TREE;
    5264              :   return NULL_TREE;
    5265              : }
    5266              : 
    5267              : // forked from gcc/cp/constexpr.cc eval_unary_expression
    5268              : 
    5269              : /* Subroutine of cxx_eval_constant_expression.
    5270              :    Attempt to reduce the unary expression tree T to a compile time value.
    5271              :    If successful, return the value.  Otherwise issue a diagnostic
    5272              :    and return error_mark_node.  */
    5273              : 
    5274              : static tree
    5275            7 : eval_unary_expression (const constexpr_ctx *ctx, tree t, bool /*lval*/,
    5276              :                        bool *non_constant_p, bool *overflow_p,
    5277              :                        tree *jump_target)
    5278              : {
    5279            7 :   tree r;
    5280            7 :   tree orig_arg = TREE_OPERAND (t, 0);
    5281            7 :   tree arg = eval_constant_expression (ctx, orig_arg, /*lval*/ false,
    5282              :                                        non_constant_p, overflow_p, jump_target);
    5283            7 :   VERIFY_CONSTANT (arg);
    5284            7 :   location_t loc = EXPR_LOCATION (t);
    5285            7 :   enum tree_code code = TREE_CODE (t);
    5286            7 :   tree type = TREE_TYPE (t);
    5287            7 :   r = fold_unary_loc (loc, code, type, arg);
    5288            7 :   if (r == NULL_TREE)
    5289              :     {
    5290            0 :       if (arg == orig_arg)
    5291              :         r = t;
    5292              :       else
    5293            0 :         r = build1_loc (loc, code, type, arg);
    5294              :     }
    5295            7 :   VERIFY_CONSTANT (r);
    5296              :   return r;
    5297              : }
    5298              : 
    5299              : // forked from gcc/cp/constexpr.cc cxx_eval_outermost_constant_expr
    5300              : 
    5301              : /* ALLOW_NON_CONSTANT is false if T is required to be a constant expression.
    5302              :    STRICT has the same sense as for constant_value_1: true if we only allow
    5303              :    conforming C++ constant expressions, or false if we want a constant value
    5304              :    even if it doesn't conform.
    5305              :    MANIFESTLY_CONST_EVAL is true if T is manifestly const-evaluated as
    5306              :    per P0595 even when ALLOW_NON_CONSTANT is true.
    5307              :    CONSTEXPR_DTOR is true when evaluating the dtor of a constexpr variable.
    5308              :    OBJECT must be non-NULL in that case.  */
    5309              : 
    5310              : static tree
    5311            0 : cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
    5312              :                                   bool strict = true,
    5313              :                                   bool manifestly_const_eval = false,
    5314              :                                   bool constexpr_dtor = false,
    5315              :                                   tree object = NULL_TREE)
    5316              : {
    5317            0 :   auto_timevar time (TV_CONSTEXPR);
    5318              : 
    5319            0 :   bool non_constant_p = false;
    5320            0 :   bool overflow_p = false;
    5321              : 
    5322            0 :   if (BRACE_ENCLOSED_INITIALIZER_P (t))
    5323              :     {
    5324            0 :       gcc_checking_assert (allow_non_constant);
    5325              :       return t;
    5326              :     }
    5327              : 
    5328            0 :   constexpr_global_ctx global_ctx;
    5329            0 :   constexpr_ctx ctx
    5330              :     = {&global_ctx, NULL,
    5331              :        NULL,        NULL,
    5332              :        NULL,        NULL,
    5333              :        NULL,        allow_non_constant,
    5334            0 :        strict,      manifestly_const_eval || !allow_non_constant};
    5335              : 
    5336              :   /* Turn off -frounding-math for manifestly constant evaluation.  */
    5337            0 :   warning_sentinel rm (flag_rounding_math, ctx.manifestly_const_eval);
    5338            0 :   tree type = initialized_type (t);
    5339            0 :   tree r = t;
    5340            0 :   bool is_consteval = false;
    5341            0 :   if (VOID_TYPE_P (type))
    5342              :     {
    5343            0 :       if (constexpr_dtor)
    5344              :         /* Used for destructors of array elements.  */
    5345            0 :         type = TREE_TYPE (object);
    5346              :       else
    5347              :         {
    5348            0 :           if (TREE_CODE (t) != CALL_EXPR)
    5349              :             return t;
    5350              :           /* Calls to immediate functions returning void need to be
    5351              :              evaluated.  */
    5352            0 :           tree fndecl = rs_get_callee_fndecl_nofold (t);
    5353            0 :           if (fndecl == NULL_TREE || !DECL_IMMEDIATE_FUNCTION_P (fndecl))
    5354              :             return t;
    5355              :           else
    5356              :             is_consteval = true;
    5357              :         }
    5358              :     }
    5359            0 :   else if ((TREE_CODE (t) == CALL_EXPR || TREE_CODE (t) == TARGET_EXPR))
    5360              :     {
    5361              :       /* For non-concept checks, determine if it is consteval.  */
    5362            0 :       tree x = t;
    5363            0 :       if (TREE_CODE (x) == TARGET_EXPR)
    5364            0 :         x = TARGET_EXPR_INITIAL (x);
    5365            0 :       tree fndecl = rs_get_callee_fndecl_nofold (x);
    5366            0 :       if (fndecl && DECL_IMMEDIATE_FUNCTION_P (fndecl))
    5367              :         is_consteval = true;
    5368              :     }
    5369            0 :   if (AGGREGATE_TYPE_P (type) || VECTOR_TYPE_P (type))
    5370              :     {
    5371              :       /* In C++14 an NSDMI can participate in aggregate initialization,
    5372              :          and can refer to the address of the object being initialized, so
    5373              :          we need to pass in the relevant VAR_DECL if we want to do the
    5374              :          evaluation in a single pass.  The evaluation will dynamically
    5375              :          update ctx.values for the VAR_DECL.  We use the same strategy
    5376              :          for C++11 constexpr constructors that refer to the object being
    5377              :          initialized.  */
    5378            0 :       if (constexpr_dtor)
    5379              :         {
    5380            0 :           gcc_assert (object && VAR_P (object));
    5381            0 :           gcc_assert (DECL_DECLARED_CONSTEXPR_P (object));
    5382            0 :           gcc_assert (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (object));
    5383            0 :           if (error_operand_p (DECL_INITIAL (object)))
    5384              :             return t;
    5385            0 :           ctx.ctor = unshare_expr (DECL_INITIAL (object));
    5386            0 :           TREE_READONLY (ctx.ctor) = false;
    5387              :           /* Temporarily force decl_really_constant_value to return false
    5388              :              for it, we want to use ctx.ctor for the current value instead.  */
    5389            0 :           DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (object) = false;
    5390              :         }
    5391              :       else
    5392              :         {
    5393            0 :           ctx.ctor = build_constructor (type, NULL);
    5394            0 :           CONSTRUCTOR_NO_CLEARING (ctx.ctor) = true;
    5395              :         }
    5396            0 :       if (!object)
    5397              :         {
    5398            0 :           if (TREE_CODE (t) == TARGET_EXPR)
    5399            0 :             object = TARGET_EXPR_SLOT (t);
    5400              :         }
    5401            0 :       ctx.object = object;
    5402            0 :       if (object)
    5403            0 :         gcc_assert (
    5404              :           same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE (object)));
    5405            0 :       if (object && DECL_P (object))
    5406            0 :         global_ctx.values.put (object, ctx.ctor);
    5407            0 :       if (TREE_CODE (r) == TARGET_EXPR)
    5408              :         /* Avoid creating another CONSTRUCTOR when we expand the
    5409              :            TARGET_EXPR.  */
    5410            0 :         r = TARGET_EXPR_INITIAL (r);
    5411              :     }
    5412              : 
    5413            0 :   auto_vec<tree, 16> cleanups;
    5414            0 :   global_ctx.cleanups = &cleanups;
    5415              : 
    5416            0 :   if (manifestly_const_eval)
    5417            0 :     instantiate_constexpr_fns (r);
    5418            0 :   tree jump_target = NULL_TREE;
    5419            0 :   r = eval_constant_expression (&ctx, r, false, &non_constant_p, &overflow_p,
    5420              :                                 &jump_target);
    5421              : 
    5422            0 :   if (!constexpr_dtor)
    5423            0 :     verify_constant (r, allow_non_constant, &non_constant_p, &overflow_p);
    5424              :   else
    5425            0 :     DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (object) = true;
    5426              : 
    5427            0 :   unsigned int i;
    5428            0 :   tree cleanup;
    5429              :   /* Evaluate the cleanups.  */
    5430            0 :   FOR_EACH_VEC_ELT_REVERSE (cleanups, i, cleanup)
    5431            0 :     eval_constant_expression (&ctx, cleanup, false, &non_constant_p,
    5432              :                               &overflow_p, NULL);
    5433              : 
    5434              :   /* Mutable logic is a bit tricky: we want to allow initialization of
    5435              :      constexpr variables with mutable members, but we can't copy those
    5436              :      members to another constexpr variable.  */
    5437            0 :   if (TREE_CODE (r) == CONSTRUCTOR && CONSTRUCTOR_MUTABLE_POISON (r))
    5438              :     {
    5439            0 :       if (!allow_non_constant)
    5440            0 :         error ("%qE is not a constant expression because it refers to "
    5441              :                "mutable subobjects of %qT",
    5442              :                t, type);
    5443            0 :       non_constant_p = true;
    5444              :     }
    5445              : 
    5446            0 :   if (TREE_CODE (r) == CONSTRUCTOR && CONSTRUCTOR_NO_CLEARING (r))
    5447              :     {
    5448            0 :       if (!allow_non_constant)
    5449            0 :         error ("%qE is not a constant expression because it refers to "
    5450              :                "an incompletely initialized variable",
    5451              :                t);
    5452            0 :       TREE_CONSTANT (r) = false;
    5453            0 :       non_constant_p = true;
    5454              :     }
    5455              : 
    5456            0 :   if (!global_ctx.heap_vars.is_empty ())
    5457              :     {
    5458            0 :       tree heap_var
    5459            0 :         = rs_walk_tree_without_duplicates (&r, find_heap_var_refs, NULL);
    5460            0 :       unsigned int i;
    5461            0 :       if (heap_var)
    5462              :         {
    5463            0 :           if (!allow_non_constant && !non_constant_p)
    5464            0 :             error_at (DECL_SOURCE_LOCATION (heap_var),
    5465              :                       "%qE is not a constant expression because it refers to "
    5466              :                       "a result of %<operator new%>",
    5467              :                       t);
    5468            0 :           r = t;
    5469            0 :           non_constant_p = true;
    5470              :         }
    5471            0 :       FOR_EACH_VEC_ELT (global_ctx.heap_vars, i, heap_var)
    5472              :         {
    5473            0 :           if (DECL_NAME (heap_var) != heap_deleted_identifier)
    5474              :             {
    5475            0 :               if (!allow_non_constant && !non_constant_p)
    5476            0 :                 error_at (DECL_SOURCE_LOCATION (heap_var),
    5477              :                           "%qE is not a constant expression because allocated "
    5478              :                           "storage has not been deallocated",
    5479              :                           t);
    5480            0 :               r = t;
    5481            0 :               non_constant_p = true;
    5482              :             }
    5483            0 :           varpool_node::get (heap_var)->remove ();
    5484              :         }
    5485              :     }
    5486              : 
    5487              :   /* Check that immediate invocation does not return an expression referencing
    5488              :      any immediate function decls.  */
    5489            0 :   if (is_consteval || in_immediate_context ())
    5490            0 :     if (tree immediate_fndecl
    5491            0 :         = rs_walk_tree_without_duplicates (&r, find_immediate_fndecl, NULL))
    5492              :       {
    5493            0 :         if (!allow_non_constant && !non_constant_p)
    5494            0 :           error_at (rs_expr_loc_or_input_loc (t),
    5495              :                     "immediate evaluation returns address of immediate "
    5496              :                     "function %qD",
    5497              :                     immediate_fndecl);
    5498            0 :         r = t;
    5499            0 :         non_constant_p = true;
    5500              :       }
    5501              : 
    5502            0 :   if (non_constant_p)
    5503              :     /* If we saw something bad, go back to our argument.  The wrapping below is
    5504              :        only for the cases of TREE_CONSTANT argument or overflow.  */
    5505            0 :     r = t;
    5506              : 
    5507            0 :   if (!non_constant_p && overflow_p)
    5508            0 :     non_constant_p = true;
    5509              : 
    5510              :   /* Unshare the result.  */
    5511            0 :   bool should_unshare = true;
    5512            0 :   if (r == t || (TREE_CODE (t) == TARGET_EXPR && TARGET_EXPR_INITIAL (t) == r))
    5513              :     should_unshare = false;
    5514              : 
    5515            0 :   if (non_constant_p && !allow_non_constant)
    5516            0 :     return error_mark_node;
    5517            0 :   else if (constexpr_dtor)
    5518              :     return r;
    5519            0 :   else if (non_constant_p && TREE_CONSTANT (r))
    5520              :     {
    5521              :       /* This isn't actually constant, so unset TREE_CONSTANT.
    5522              :          Don't clear TREE_CONSTANT on ADDR_EXPR, as the middle-end requires
    5523              :          it to be set if it is invariant address, even when it is not
    5524              :          a valid C++ constant expression.  Wrap it with a NOP_EXPR
    5525              :          instead.  */
    5526            0 :       if (EXPR_P (r) && TREE_CODE (r) != ADDR_EXPR)
    5527            0 :         r = copy_node (r);
    5528            0 :       else if (TREE_CODE (r) == CONSTRUCTOR)
    5529            0 :         r = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (r), r);
    5530              :       else
    5531            0 :         r = build_nop (TREE_TYPE (r), r);
    5532            0 :       TREE_CONSTANT (r) = false;
    5533              :     }
    5534            0 :   else if (non_constant_p)
    5535              :     return t;
    5536              : 
    5537            0 :   if (should_unshare)
    5538            0 :     r = unshare_expr (r);
    5539              : 
    5540            0 :   if (TREE_CODE (r) == CONSTRUCTOR && CLASS_TYPE_P (TREE_TYPE (r)))
    5541              :     {
    5542            0 :       r = adjust_temp_type (type, r);
    5543            0 :       if (TREE_CODE (t) == TARGET_EXPR && TARGET_EXPR_INITIAL (t) == r)
    5544              :         return t;
    5545              :     }
    5546              : 
    5547              :   /* Remember the original location if that wouldn't need a wrapper.  */
    5548            0 :   if (location_t loc = EXPR_LOCATION (t))
    5549            0 :     protected_set_expr_location (r, loc);
    5550              : 
    5551            0 :   return r;
    5552            0 : }
    5553              : 
    5554              : /* Like is_constant_expression, but allow const variables that are not allowed
    5555              :    under constexpr rules.  */
    5556              : 
    5557              : bool
    5558            0 : is_static_init_expression (tree t)
    5559              : {
    5560            0 :   return potential_constant_expression_1 (t, false, false, true, tf_none);
    5561              : }
    5562              : 
    5563              : /* Like potential_constant_expression, but don't consider possible constexpr
    5564              :    substitution of the current function.  That is, PARM_DECL qualifies under
    5565              :    potential_constant_expression, but not here.
    5566              : 
    5567              :    This is basically what you can check when any actual constant values might
    5568              :    be value-dependent.  */
    5569              : 
    5570              : bool
    5571            0 : is_constant_expression (tree t)
    5572              : {
    5573            0 :   return potential_constant_expression_1 (t, false, true, true, tf_none);
    5574              : }
    5575              : 
    5576              : /* Returns true if T is a potential static initializer expression that is not
    5577              :    instantiation-dependent.  */
    5578              : 
    5579              : bool
    5580            0 : is_nondependent_static_init_expression (tree t)
    5581              : {
    5582            0 :   return (!type_unknown_p (t) && is_static_init_expression (t));
    5583              : }
    5584              : 
    5585              : /* Like maybe_constant_value, but returns a CONSTRUCTOR directly, rather
    5586              :    than wrapped in a TARGET_EXPR.
    5587              :    ALLOW_NON_CONSTANT is false if T is required to be a constant expression.
    5588              :    MANIFESTLY_CONST_EVAL is true if T is manifestly const-evaluated as
    5589              :    per P0595 even when ALLOW_NON_CONSTANT is true.  */
    5590              : 
    5591              : static tree
    5592            0 : maybe_constant_init_1 (tree t, tree decl, bool allow_non_constant,
    5593              :                        bool manifestly_const_eval)
    5594              : {
    5595            0 :   if (!t)
    5596              :     return t;
    5597            0 :   if (TREE_CODE (t) == EXPR_STMT)
    5598            0 :     t = TREE_OPERAND (t, 0);
    5599            0 :   if (TREE_CODE (t) == CONVERT_EXPR && VOID_TYPE_P (TREE_TYPE (t)))
    5600            0 :     t = TREE_OPERAND (t, 0);
    5601            0 :   if (TREE_CODE (t) == INIT_EXPR)
    5602            0 :     t = TREE_OPERAND (t, 1);
    5603            0 :   if (TREE_CODE (t) == TARGET_EXPR)
    5604            0 :     t = TARGET_EXPR_INITIAL (t);
    5605            0 :   if (!is_nondependent_static_init_expression (t))
    5606              :     /* Don't try to evaluate it.  */;
    5607            0 :   else if (CONSTANT_CLASS_P (t) && allow_non_constant)
    5608              :     /* No evaluation needed.  */;
    5609              :   else
    5610            0 :     t = cxx_eval_outermost_constant_expr (t, allow_non_constant,
    5611              :                                           /*strict*/ false,
    5612              :                                           manifestly_const_eval, false, decl);
    5613            0 :   if (TREE_CODE (t) == TARGET_EXPR)
    5614              :     {
    5615            0 :       tree init = TARGET_EXPR_INITIAL (t);
    5616            0 :       if (TREE_CODE (init) == CONSTRUCTOR)
    5617            0 :         t = init;
    5618              :     }
    5619              :   return t;
    5620              : }
    5621              : 
    5622              : /* Wrapper for maybe_constant_init_1 which permits non constants.  */
    5623              : 
    5624              : tree
    5625            0 : maybe_constant_init (tree t, tree decl, bool manifestly_const_eval)
    5626              : {
    5627            0 :   return maybe_constant_init_1 (t, decl, true, manifestly_const_eval);
    5628              : }
    5629              : 
    5630              : /* Returns true if T is a potential constant expression that is not
    5631              :    instantiation-dependent, and therefore a candidate for constant folding even
    5632              :    in a template.  */
    5633              : 
    5634              : bool
    5635            0 : is_nondependent_constant_expression (tree t)
    5636              : {
    5637            0 :   return (!type_unknown_p (t) && is_constant_expression (t)
    5638            0 :           && !instantiation_dependent_expression_p (t));
    5639              : }
    5640              : 
    5641              : // forked from gcc/cp/parser.cc cp_unevaluated_operand
    5642              : 
    5643              : /* Nonzero if we are parsing an unevaluated operand: an operand to
    5644              :    sizeof, typeof, or alignof.  */
    5645              : int cp_unevaluated_operand;
    5646              : 
    5647              : // forked from gcc/cp/constexpr.cc cv_cache
    5648              : 
    5649              : /* If T is a constant expression, returns its reduced value.
    5650              :    Otherwise, if T does not have TREE_CONSTANT set, returns T.
    5651              :    Otherwise, returns a version of T without TREE_CONSTANT.
    5652              :    MANIFESTLY_CONST_EVAL is true if T is manifestly const-evaluated
    5653              :    as per P0595.  */
    5654              : 
    5655              : static GTY ((deletable)) hash_map<tree, tree> *cv_cache;
    5656              : 
    5657              : // forked from gcc/cp/constexpr.cc maybe_constant_value
    5658              : 
    5659              : tree
    5660            0 : maybe_constant_value (tree t, tree decl, bool manifestly_const_eval)
    5661              : {
    5662            0 :   tree r;
    5663              : 
    5664            0 :   if (!is_nondependent_constant_expression (t))
    5665              :     {
    5666            0 :       if (TREE_OVERFLOW_P (t))
    5667              :         {
    5668            0 :           t = build_nop (TREE_TYPE (t), t);
    5669            0 :           TREE_CONSTANT (t) = false;
    5670              :         }
    5671            0 :       return t;
    5672              :     }
    5673            0 :   else if (CONSTANT_CLASS_P (t))
    5674              :     /* No caching or evaluation needed.  */
    5675              :     return t;
    5676              : 
    5677            0 :   if (manifestly_const_eval)
    5678            0 :     return cxx_eval_outermost_constant_expr (t, true, true, true, false, decl);
    5679              : 
    5680            0 :   if (cv_cache == NULL)
    5681            0 :     cv_cache = hash_map<tree, tree>::create_ggc (101);
    5682            0 :   if (tree *cached = cv_cache->get (t))
    5683              :     {
    5684            0 :       r = *cached;
    5685            0 :       if (r != t)
    5686              :         {
    5687              :           // Faisal: commenting this out as not sure if it's needed and it's
    5688              :           // huge r = break_out_target_exprs (r, /*clear_loc*/true);
    5689            0 :           protected_set_expr_location (r, EXPR_LOCATION (t));
    5690              :         }
    5691              :       return r;
    5692              :     }
    5693              : 
    5694              :   /* Don't evaluate an unevaluated operand.  */
    5695            0 :   if (cp_unevaluated_operand)
    5696              :     return t;
    5697              : 
    5698            0 :   uid_sensitive_constexpr_evaluation_checker c;
    5699            0 :   r = cxx_eval_outermost_constant_expr (t, true, true, false, false, decl);
    5700            0 :   gcc_checking_assert (
    5701              :     r == t || CONVERT_EXPR_P (t) || TREE_CODE (t) == VIEW_CONVERT_EXPR
    5702              :     || (TREE_CONSTANT (t) && !TREE_CONSTANT (r)) || !rs_tree_equal (r, t));
    5703            0 :   if (!c.evaluation_restricted_p ())
    5704            0 :     cv_cache->put (t, r);
    5705              :   return r;
    5706              : }
    5707              : 
    5708              : // forked from gcc/cp/constexpr.cc
    5709              : 
    5710              : bool
    5711            0 : potential_constant_expression (tree t)
    5712              : {
    5713            0 :   return potential_constant_expression_1 (t, false, true, false, tf_none);
    5714              : }
    5715              : 
    5716              : /* Data structure for passing data from potential_constant_expression_1
    5717              :    to check_for_return_continue via cp_walk_tree.  */
    5718              : struct check_for_return_continue_data
    5719              : {
    5720              :   hash_set<tree> *pset;
    5721              :   tree continue_stmt;
    5722              :   tree break_stmt;
    5723              : };
    5724              : 
    5725              : /* Helper function for potential_constant_expression_1 SWITCH_STMT handling,
    5726              :    called through cp_walk_tree.  Return the first RETURN_EXPR found, or note
    5727              :    the first CONTINUE_STMT and/or BREAK_STMT if RETURN_EXPR is not found.  */
    5728              : static tree
    5729            0 : check_for_return_continue (tree *tp, int *walk_subtrees, void *data)
    5730              : {
    5731            0 :   tree t = *tp, s, b;
    5732            0 :   check_for_return_continue_data *d = (check_for_return_continue_data *) data;
    5733            0 :   switch (TREE_CODE (t))
    5734              :     {
    5735              :     case RETURN_EXPR:
    5736              :       return t;
    5737              : 
    5738            0 :     case CONTINUE_STMT:
    5739            0 :       if (d->continue_stmt == NULL_TREE)
    5740            0 :         d->continue_stmt = t;
    5741              :       break;
    5742              : 
    5743            0 :     case BREAK_STMT:
    5744            0 :       if (d->break_stmt == NULL_TREE)
    5745            0 :         d->break_stmt = t;
    5746              :       break;
    5747              : 
    5748              : #define RECUR(x)                                                               \
    5749              :   if (tree r = rs_walk_tree (&x, check_for_return_continue, data, d->pset))    \
    5750              :   return r
    5751              : 
    5752              :       /* For loops, walk subtrees manually, so that continue stmts found
    5753              :          inside of the bodies of the loops are ignored.  */
    5754              : 
    5755            0 :     case WHILE_STMT:
    5756            0 :       *walk_subtrees = 0;
    5757            0 :       RECUR (WHILE_COND (t));
    5758            0 :       s = d->continue_stmt;
    5759            0 :       b = d->break_stmt;
    5760            0 :       RECUR (WHILE_BODY (t));
    5761            0 :       d->continue_stmt = s;
    5762            0 :       d->break_stmt = b;
    5763            0 :       break;
    5764              : 
    5765            0 :     case FOR_STMT:
    5766            0 :       *walk_subtrees = 0;
    5767            0 :       RECUR (FOR_INIT_STMT (t));
    5768            0 :       RECUR (FOR_COND (t));
    5769            0 :       RECUR (FOR_EXPR (t));
    5770            0 :       s = d->continue_stmt;
    5771            0 :       b = d->break_stmt;
    5772            0 :       RECUR (FOR_BODY (t));
    5773            0 :       d->continue_stmt = s;
    5774            0 :       d->break_stmt = b;
    5775            0 :       break;
    5776              : 
    5777            0 :     case RANGE_FOR_STMT:
    5778            0 :       *walk_subtrees = 0;
    5779            0 :       RECUR (RANGE_FOR_EXPR (t));
    5780            0 :       s = d->continue_stmt;
    5781            0 :       b = d->break_stmt;
    5782            0 :       RECUR (RANGE_FOR_BODY (t));
    5783            0 :       d->continue_stmt = s;
    5784            0 :       d->break_stmt = b;
    5785            0 :       break;
    5786              : 
    5787            0 :     case SWITCH_STMT:
    5788            0 :       *walk_subtrees = 0;
    5789            0 :       RECUR (SWITCH_STMT_COND (t));
    5790            0 :       b = d->break_stmt;
    5791            0 :       RECUR (SWITCH_STMT_BODY (t));
    5792            0 :       d->break_stmt = b;
    5793            0 :       break;
    5794              : #undef RECUR
    5795              : 
    5796              :     case STATEMENT_LIST:
    5797              :     case CONSTRUCTOR:
    5798              :       break;
    5799              : 
    5800            0 :     default:
    5801            0 :       if (!EXPR_P (t))
    5802            0 :         *walk_subtrees = 0;
    5803              :       break;
    5804              :     }
    5805              : 
    5806              :   return NULL_TREE;
    5807              : }
    5808              : 
    5809              : /* Returns the namespace that contains DECL, whether directly or
    5810              :    indirectly.  */
    5811              : 
    5812              : tree
    5813            0 : decl_namespace_context (tree decl)
    5814              : {
    5815            0 :   while (1)
    5816              :     {
    5817            0 :       if (TREE_CODE (decl) == NAMESPACE_DECL)
    5818            0 :         return decl;
    5819            0 :       else if (TYPE_P (decl))
    5820            0 :         decl = CP_DECL_CONTEXT (TYPE_MAIN_DECL (decl));
    5821              :       else
    5822            0 :         decl = CP_DECL_CONTEXT (decl);
    5823              :     }
    5824              : }
    5825              : 
    5826              : /* Returns true if DECL is in the std namespace.  */
    5827              : 
    5828              : bool
    5829            0 : decl_in_std_namespace_p (tree decl)
    5830              : {
    5831            0 :   while (decl)
    5832              :     {
    5833            0 :       decl = decl_namespace_context (decl);
    5834            0 :       if (DECL_NAMESPACE_STD_P (decl))
    5835              :         return true;
    5836              :       /* Allow inline namespaces inside of std namespace, e.g. with
    5837              :          --enable-symvers=gnu-versioned-namespace std::forward would be
    5838              :          actually std::_8::forward.  */
    5839            0 :       if (!DECL_NAMESPACE_INLINE_P (decl))
    5840              :         return false;
    5841            0 :       decl = CP_DECL_CONTEXT (decl);
    5842              :     }
    5843              :   return false;
    5844              : }
    5845              : 
    5846              : /* Return true if FNDECL is std::construct_at.  */
    5847              : 
    5848              : static inline bool
    5849              : is_std_construct_at (tree fndecl)
    5850              : {
    5851              :   if (!decl_in_std_namespace_p (fndecl))
    5852              :     return false;
    5853              : 
    5854              :   tree name = DECL_NAME (fndecl);
    5855              :   return name && id_equal (name, "construct_at");
    5856              : }
    5857              : 
    5858              : /* Return true if FNDECL is __dynamic_cast.  */
    5859              : 
    5860              : static inline bool
    5861              : cxx_dynamic_cast_fn_p (tree fndecl)
    5862              : {
    5863              :   return (id_equal (DECL_NAME (fndecl), "__dynamic_cast")
    5864              :           && CP_DECL_CONTEXT (fndecl) == global_namespace);
    5865              : }
    5866              : 
    5867              : /* Return true if FNDECL is std::allocator<T>::{,de}allocate.  */
    5868              : 
    5869              : static inline bool
    5870              : is_std_allocator_allocate (tree fndecl)
    5871              : {
    5872              :   tree name = DECL_NAME (fndecl);
    5873              :   if (name == NULL_TREE
    5874              :       || !(id_equal (name, "allocate") || id_equal (name, "deallocate")))
    5875              :     return false;
    5876              : 
    5877              :   tree ctx = DECL_CONTEXT (fndecl);
    5878              :   if (ctx == NULL_TREE || !CLASS_TYPE_P (ctx) || !TYPE_MAIN_DECL (ctx))
    5879              :     return false;
    5880              : 
    5881              :   tree decl = TYPE_MAIN_DECL (ctx);
    5882              :   name = DECL_NAME (decl);
    5883              :   if (name == NULL_TREE || !id_equal (name, "allocator"))
    5884              :     return false;
    5885              : 
    5886              :   return decl_in_std_namespace_p (decl);
    5887              : }
    5888              : 
    5889              : /* Overload for the above taking rust_constexpr_call*.  */
    5890              : 
    5891              : static inline bool
    5892              : is_std_allocator_allocate (const rust_constexpr_call *call)
    5893              : {
    5894              :   return (call && call->fundef
    5895              :           && is_std_allocator_allocate (call->fundef->decl));
    5896              : }
    5897              : 
    5898              : /* Return true if T denotes a potentially constant expression.  Issue
    5899              :    diagnostic as appropriate under control of FLAGS.  If WANT_RVAL is true,
    5900              :    an lvalue-rvalue conversion is implied.  If NOW is true, we want to
    5901              :    consider the expression in the current context, independent of constexpr
    5902              :    substitution.
    5903              : 
    5904              :    C++0x [expr.const] used to say
    5905              : 
    5906              :    6 An expression is a potential constant expression if it is
    5907              :      a constant expression where all occurrences of function
    5908              :      parameters are replaced by arbitrary constant expressions
    5909              :      of the appropriate type.
    5910              : 
    5911              :    2  A conditional expression is a constant expression unless it
    5912              :       involves one of the following as a potentially evaluated
    5913              :       subexpression (3.2), but subexpressions of logical AND (5.14),
    5914              :       logical OR (5.15), and conditional (5.16) operations that are
    5915              :       not evaluated are not considered.   */
    5916              : 
    5917              : static bool
    5918            0 : potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
    5919              :                                  tsubst_flags_t flags, tree *jump_target)
    5920              : {
    5921              : #define RECUR(T, RV)                                                           \
    5922              :   potential_constant_expression_1 ((T), (RV), strict, now, flags, jump_target)
    5923              : 
    5924            0 :   enum
    5925              :   {
    5926              :     any = false,
    5927              :     rval = true
    5928              :   };
    5929            0 :   int i;
    5930            0 :   tree tmp;
    5931              : 
    5932            0 :   if (t == error_mark_node)
    5933              :     return false;
    5934            0 :   if (t == NULL_TREE)
    5935              :     return true;
    5936            0 :   location_t loc = rs_expr_loc_or_input_loc (t);
    5937              : 
    5938            0 :   if (*jump_target)
    5939              :     /* If we are jumping, ignore everything.  This is simpler than the
    5940              :        cxx_eval_constant_expression handling because we only need to be
    5941              :        conservatively correct, and we don't necessarily have a constant value
    5942              :        available, so we don't bother with switch tracking.  */
    5943              :     return true;
    5944              : 
    5945            0 :   if (TREE_THIS_VOLATILE (t) && want_rval)
    5946              :     {
    5947            0 :       if (flags & tf_error)
    5948            0 :         error_at (loc,
    5949              :                   "lvalue-to-rvalue conversion of a volatile lvalue "
    5950              :                   "%qE with type %qT",
    5951            0 :                   t, TREE_TYPE (t));
    5952              :       return false;
    5953              :     }
    5954            0 :   if (CONSTANT_CLASS_P (t))
    5955              :     return true;
    5956            0 :   if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_TYPED)
    5957            0 :       && TREE_TYPE (t) == error_mark_node)
    5958              :     return false;
    5959              : 
    5960            0 :   switch (TREE_CODE (t))
    5961              :     {
    5962              :     case FUNCTION_DECL:
    5963              :     case OVERLOAD:
    5964              :     case LABEL_DECL:
    5965              :     case CASE_LABEL_EXPR:
    5966              :     case PREDICT_EXPR:
    5967              :     case CONST_DECL:
    5968              :     case IDENTIFIER_NODE:
    5969              :       /* We can see a FIELD_DECL in a pointer-to-member expression.  */
    5970              :     case FIELD_DECL:
    5971              :     case RESULT_DECL:
    5972              :     case PLACEHOLDER_EXPR:
    5973              :     case STATIC_ASSERT:
    5974              :       return true;
    5975              : 
    5976            0 :     case RETURN_EXPR:
    5977            0 :       if (!RECUR (TREE_OPERAND (t, 0), any))
    5978              :         return false;
    5979              :       /* FALLTHROUGH */
    5980              : 
    5981            0 :     case BREAK_STMT:
    5982            0 :     case CONTINUE_STMT:
    5983            0 :       *jump_target = t;
    5984            0 :       return true;
    5985              : 
    5986            0 :     case PARM_DECL:
    5987            0 :       if (now && want_rval)
    5988              :         {
    5989            0 :           tree type = TREE_TYPE (t);
    5990            0 :           if (is_really_empty_class (type, /*ignore_vptr*/ false))
    5991              :             /* An empty class has no data to read.  */
    5992              :             return true;
    5993            0 :           if (flags & tf_error)
    5994            0 :             error ("%qE is not a constant expression", t);
    5995              :           return false;
    5996              :         }
    5997              :       return true;
    5998              : 
    5999            0 :     case CALL_EXPR:
    6000              :       /* -- an invocation of a function other than a constexpr function
    6001              :             or a constexpr constructor.  */
    6002            0 :       {
    6003            0 :         tree fun = get_function_named_in_call (t);
    6004            0 :         const int nargs = call_expr_nargs (t);
    6005            0 :         i = 0;
    6006              : 
    6007            0 :         if (fun == NULL_TREE)
    6008              :           {
    6009              :             /* Reset to allow the function to continue past the end
    6010              :                of the block below.  Otherwise return early.  */
    6011            0 :             bool bail = true;
    6012              : 
    6013            0 :             if (TREE_CODE (t) == CALL_EXPR && CALL_EXPR_FN (t) == NULL_TREE)
    6014            0 :               switch (CALL_EXPR_IFN (t))
    6015              :                 {
    6016              :                 /* These should be ignored, they are optimized away from
    6017              :                    constexpr functions.  */
    6018              :                 case IFN_UBSAN_NULL:
    6019              :                 case IFN_UBSAN_BOUNDS:
    6020              :                 case IFN_UBSAN_VPTR:
    6021              :                 case IFN_FALLTHROUGH:
    6022              :                   return true;
    6023              : 
    6024              :                 case IFN_ADD_OVERFLOW:
    6025              :                 case IFN_SUB_OVERFLOW:
    6026              :                 case IFN_MUL_OVERFLOW:
    6027              :                 case IFN_LAUNDER:
    6028              :                 case IFN_VEC_CONVERT:
    6029              :                   bail = false;
    6030              :                   break;
    6031              : 
    6032              :                 default:
    6033              :                   break;
    6034              :                 }
    6035              : 
    6036              :             if (bail)
    6037              :               {
    6038              :                 /* fold_call_expr can't do anything with IFN calls.  */
    6039            0 :                 if (flags & tf_error)
    6040            0 :                   error_at (loc, "call to internal function %qE", t);
    6041              :                 return false;
    6042              :               }
    6043              :           }
    6044              : 
    6045            0 :         if (fun && is_overloaded_fn (fun))
    6046              :           {
    6047            0 :             if (TREE_CODE (fun) == FUNCTION_DECL)
    6048              :               {
    6049            0 :                 if (builtin_valid_in_constant_expr_p (fun))
    6050              :                   return true;
    6051            0 :                 if (!maybe_constexpr_fn (fun)
    6052              :                     /* Allow any built-in function; if the expansion
    6053              :                        isn't constant, we'll deal with that then.  */
    6054            0 :                     && !fndecl_built_in_p (fun)
    6055              :                     /* In C++20, replaceable global allocation functions
    6056              :                        are constant expressions.  */
    6057            0 :                     && (/* !cxx_replaceable_global_alloc_fn (fun)
    6058            0 :                         ||*/ TREE_CODE (t) != CALL_EXPR
    6059            0 :                         || (!CALL_FROM_NEW_OR_DELETE_P (t)
    6060            0 :                             && (current_function_decl == NULL_TREE
    6061              :                                 /*|| !is_std_allocator_allocate(current_function_decl)*/)))
    6062              :                     /* Allow placement new in std::construct_at.  */
    6063            0 :                     && (/*!cxx_placement_new_fn (fun)
    6064              :                         ||*/ TREE_CODE (t) != CALL_EXPR
    6065            0 :                         || current_function_decl == NULL_TREE
    6066              :                         /*|| !is_std_construct_at (current_function_decl)*/)
    6067              :                   /*  && !cxx_dynamic_cast_fn_p (fun)*/)
    6068              :                   {
    6069            0 :                     if (flags & tf_error)
    6070              :                       {
    6071            0 :                         error_at (loc, "call to non-%<constexpr%> function %qD",
    6072              :                                   fun);
    6073            0 :                         explain_invalid_constexpr_fn (fun);
    6074              :                       }
    6075              :                     return false;
    6076              :                   }
    6077              :                 /* A call to a non-static member function takes the address
    6078              :                    of the object as the first argument.  But in a constant
    6079              :                    expression the address will be folded away, so look
    6080              :                    through it now.  */
    6081            0 :                 if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fun)
    6082            0 :                     && !DECL_CONSTRUCTOR_P (fun))
    6083              :                   {
    6084            0 :                     tree x = CALL_EXPR_ARG (t, 0);
    6085              : 
    6086              :                     /* Don't require an immediately constant value, as
    6087              :                        constexpr substitution might not use the value.  */
    6088            0 :                     bool sub_now = false;
    6089            0 :                     if (!potential_constant_expression_1 (x, rval, strict,
    6090              :                                                           sub_now, flags,
    6091              :                                                           jump_target))
    6092              :                       return false;
    6093              :                     i = 1;
    6094              :                   }
    6095              :               }
    6096              :             else
    6097              :               {
    6098            0 :                 if (!RECUR (fun, true))
    6099              :                   return false;
    6100            0 :                 fun = get_first_fn (fun);
    6101              :               }
    6102            0 :             fun = DECL_ORIGIN (fun);
    6103              :           }
    6104            0 :         else if (fun)
    6105              :           {
    6106            0 :             if (RECUR (fun, rval))
    6107              :               /* Might end up being a constant function pointer.  */;
    6108              :             else
    6109              :               return false;
    6110              :           }
    6111            0 :         for (; i < nargs; ++i)
    6112              :           {
    6113            0 :             tree x = CALL_EXPR_ARG (t, i);
    6114              :             /* In a template, reference arguments haven't been converted to
    6115              :                REFERENCE_TYPE and we might not even know if the parameter
    6116              :                is a reference, so accept lvalue constants too.  */
    6117            0 :             bool rv = rval;
    6118              :             /* Don't require an immediately constant value, as constexpr
    6119              :                substitution might not use the value of the argument.  */
    6120            0 :             bool sub_now = false;
    6121            0 :             if (!potential_constant_expression_1 (x, rv, strict, sub_now, flags,
    6122              :                                                   jump_target))
    6123              :               return false;
    6124              :           }
    6125              :         return true;
    6126              :       }
    6127              : 
    6128            0 :     case NON_LVALUE_EXPR:
    6129              :       /* -- an lvalue-to-rvalue conversion (4.1) unless it is applied to
    6130              :             -- an lvalue of integral type that refers to a non-volatile
    6131              :                const variable or static data member initialized with
    6132              :                constant expressions, or
    6133              : 
    6134              :             -- an lvalue of literal type that refers to non-volatile
    6135              :                object defined with constexpr, or that refers to a
    6136              :                sub-object of such an object;  */
    6137            0 :       return RECUR (TREE_OPERAND (t, 0), rval);
    6138              : 
    6139            0 :     case VAR_DECL:
    6140            0 :       if (DECL_HAS_VALUE_EXPR_P (t))
    6141              :         {
    6142            0 :           return RECUR (DECL_VALUE_EXPR (t), rval);
    6143              :         }
    6144            0 :       if (want_rval && !var_in_maybe_constexpr_fn (t)
    6145            0 :           && !decl_maybe_constant_var_p (t)
    6146            0 :           && (strict || !RS_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (t))
    6147            0 :               || (DECL_INITIAL (t)
    6148            0 :                   && !DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (t)))
    6149            0 :           && COMPLETE_TYPE_P (TREE_TYPE (t))
    6150            0 :           && !is_really_empty_class (TREE_TYPE (t), /*ignore_vptr*/ false))
    6151              :         {
    6152            0 :           if (flags & tf_error)
    6153            0 :             non_const_var_error (loc, t);
    6154              :           return false;
    6155              :         }
    6156              :       return true;
    6157              : 
    6158              :       /* FALLTHRU */
    6159            0 :     case NOP_EXPR:
    6160            0 :     case CONVERT_EXPR:
    6161            0 :     case VIEW_CONVERT_EXPR:
    6162              :       /* -- a reinterpret_cast.  FIXME not implemented, and this rule
    6163              :          may change to something more specific to type-punning (DR 1312).  */
    6164            0 :       {
    6165            0 :         tree from = TREE_OPERAND (t, 0);
    6166            0 :         if (location_wrapper_p (t))
    6167              :           return (RECUR (from, want_rval));
    6168            0 :         if (INDIRECT_TYPE_P (TREE_TYPE (t)))
    6169              :           {
    6170            0 :             STRIP_ANY_LOCATION_WRAPPER (from);
    6171            0 :             if (TREE_CODE (from) == INTEGER_CST && !integer_zerop (from))
    6172              :               {
    6173            0 :                 if (flags & tf_error)
    6174            0 :                   error_at (loc,
    6175              :                             "%<reinterpret_cast%> from integer to pointer");
    6176              :                 return false;
    6177              :               }
    6178              :           }
    6179            0 :         return (RECUR (from, TREE_CODE (t) != VIEW_CONVERT_EXPR));
    6180              :       }
    6181              : 
    6182            0 :     case ADDR_EXPR:
    6183              :       /* -- a unary operator & that is applied to an lvalue that
    6184              :             designates an object with thread or automatic storage
    6185              :             duration;  */
    6186            0 :       t = TREE_OPERAND (t, 0);
    6187              : 
    6188            0 :       if (TREE_CODE (t) == OFFSET_REF && PTRMEM_OK_P (t))
    6189              :         /* A pointer-to-member constant.  */
    6190              :         return true;
    6191              : 
    6192              : #if 0
    6193              :       /* FIXME adjust when issue 1197 is fully resolved.  For now don't do
    6194              :          any checking here, as we might dereference the pointer later.  If
    6195              :          we remove this code, also remove check_automatic_or_tls.  */
    6196              :       i = check_automatic_or_tls (t);
    6197              :       if (i == ck_ok)
    6198              :         return true;
    6199              :       if (i == ck_bad)
    6200              :         {
    6201              :           if (flags & tf_error)
    6202              :             error ("address-of an object %qE with thread local or "
    6203              :                    "automatic storage is not a constant expression", t);
    6204              :           return false;
    6205              :         }
    6206              : #endif
    6207              :       return RECUR (t, any);
    6208              : 
    6209            0 :     case COMPONENT_REF:
    6210              :       /* -- a class member access unless its postfix-expression is
    6211              :             of literal type or of pointer to literal type.  */
    6212              :       /* This test would be redundant, as it follows from the
    6213              :          postfix-expression being a potential constant expression.  */
    6214            0 :       if (type_unknown_p (t))
    6215              :         return true;
    6216            0 :       if (is_overloaded_fn (t))
    6217              :         /* In a template, a COMPONENT_REF of a function expresses ob.fn(),
    6218              :            which uses ob as an lvalue.  */
    6219            0 :         want_rval = false;
    6220            0 :       gcc_fallthrough ();
    6221              : 
    6222            0 :     case REALPART_EXPR:
    6223            0 :     case IMAGPART_EXPR:
    6224            0 :     case BIT_FIELD_REF:
    6225            0 :       return RECUR (TREE_OPERAND (t, 0), want_rval);
    6226              : 
    6227            0 :     case INDIRECT_REF:
    6228            0 :       {
    6229            0 :         tree x = TREE_OPERAND (t, 0);
    6230            0 :         STRIP_NOPS (x);
    6231            0 :         return RECUR (x, rval);
    6232              :       }
    6233              : 
    6234            0 :     case STATEMENT_LIST:
    6235            0 :       for (tree stmt : tsi_range (t))
    6236            0 :         if (!RECUR (stmt, any))
    6237            0 :           return false;
    6238              :       return true;
    6239              : 
    6240            0 :     case MODIFY_EXPR:
    6241            0 :       if (!RECUR (TREE_OPERAND (t, 0), any))
    6242              :         return false;
    6243              :       /* Just ignore clobbers.  */
    6244            0 :       if (TREE_CLOBBER_P (TREE_OPERAND (t, 1)))
    6245              :         return true;
    6246            0 :       if (!RECUR (TREE_OPERAND (t, 1), rval))
    6247              :         return false;
    6248              :       return true;
    6249              : 
    6250            0 :     case FOR_STMT:
    6251            0 :       if (!RECUR (FOR_INIT_STMT (t), any))
    6252              :         return false;
    6253            0 :       tmp = FOR_COND (t);
    6254            0 :       if (!RECUR (tmp, rval))
    6255              :         return false;
    6256            0 :       if (tmp)
    6257              :         {
    6258            0 :           tmp = cxx_eval_outermost_constant_expr (tmp, true);
    6259              :           /* If we couldn't evaluate the condition, it might not ever be
    6260              :              true.  */
    6261            0 :           if (!integer_onep (tmp))
    6262              :             {
    6263              :               /* Before returning true, check if the for body can contain
    6264              :                  a return.  */
    6265            0 :               hash_set<tree> pset;
    6266            0 :               check_for_return_continue_data data
    6267            0 :                 = {&pset, NULL_TREE, NULL_TREE};
    6268            0 :               if (tree ret_expr
    6269            0 :                   = rs_walk_tree (&FOR_BODY (t), check_for_return_continue,
    6270              :                                   &data, &pset))
    6271            0 :                 *jump_target = ret_expr;
    6272            0 :               return true;
    6273            0 :             }
    6274              :         }
    6275            0 :       if (!RECUR (FOR_EXPR (t), any))
    6276              :         return false;
    6277            0 :       if (!RECUR (FOR_BODY (t), any))
    6278              :         return false;
    6279            0 :       if (breaks (jump_target) || continues (jump_target))
    6280            0 :         *jump_target = NULL_TREE;
    6281              :       return true;
    6282              : 
    6283            0 :     case WHILE_STMT:
    6284            0 :       tmp = WHILE_COND (t);
    6285            0 :       if (!RECUR (tmp, rval))
    6286              :         return false;
    6287              : 
    6288            0 :       tmp = cxx_eval_outermost_constant_expr (tmp, true);
    6289              :       /* If we couldn't evaluate the condition, it might not ever be true.  */
    6290            0 :       if (!integer_onep (tmp))
    6291              :         {
    6292              :           /* Before returning true, check if the while body can contain
    6293              :              a return.  */
    6294            0 :           hash_set<tree> pset;
    6295            0 :           check_for_return_continue_data data = {&pset, NULL_TREE, NULL_TREE};
    6296            0 :           if (tree ret_expr
    6297            0 :               = rs_walk_tree (&WHILE_BODY (t), check_for_return_continue, &data,
    6298              :                               &pset))
    6299            0 :             *jump_target = ret_expr;
    6300            0 :           return true;
    6301            0 :         }
    6302            0 :       if (!RECUR (WHILE_BODY (t), any))
    6303              :         return false;
    6304            0 :       if (breaks (jump_target) || continues (jump_target))
    6305            0 :         *jump_target = NULL_TREE;
    6306              :       return true;
    6307              : 
    6308            0 :     case SWITCH_STMT:
    6309            0 :       if (!RECUR (SWITCH_STMT_COND (t), rval))
    6310              :         return false;
    6311              :       /* FIXME we don't check SWITCH_STMT_BODY currently, because even
    6312              :          unreachable labels would be checked and it is enough if there is
    6313              :          a single switch cond value for which it is a valid constant
    6314              :          expression.  We need to check if there are any RETURN_EXPRs
    6315              :          or CONTINUE_STMTs inside of the body though, as in that case
    6316              :          we need to set *jump_target.  */
    6317              :       else
    6318              :         {
    6319            0 :           hash_set<tree> pset;
    6320            0 :           check_for_return_continue_data data = {&pset, NULL_TREE, NULL_TREE};
    6321            0 :           if (tree ret_expr
    6322            0 :               = rs_walk_tree (&SWITCH_STMT_BODY (t), check_for_return_continue,
    6323              :                               &data, &pset))
    6324              :             /* The switch might return.  */
    6325            0 :             *jump_target = ret_expr;
    6326            0 :           else if (data.continue_stmt)
    6327              :             /* The switch can't return, but might continue.  */
    6328            0 :             *jump_target = data.continue_stmt;
    6329            0 :         }
    6330            0 :       return true;
    6331              : 
    6332            0 :     case DYNAMIC_CAST_EXPR:
    6333            0 :     case PSEUDO_DTOR_EXPR:
    6334            0 :     case NEW_EXPR:
    6335            0 :     case VEC_NEW_EXPR:
    6336            0 :     case DELETE_EXPR:
    6337            0 :     case VEC_DELETE_EXPR:
    6338            0 :     case THROW_EXPR:
    6339            0 :     case OMP_PARALLEL:
    6340            0 :     case OMP_TASK:
    6341            0 :     case OMP_FOR:
    6342            0 :     case OMP_SIMD:
    6343            0 :     case OMP_DISTRIBUTE:
    6344            0 :     case OMP_TASKLOOP:
    6345            0 :     case OMP_LOOP:
    6346            0 :     case OMP_TEAMS:
    6347            0 :     case OMP_TARGET_DATA:
    6348            0 :     case OMP_TARGET:
    6349            0 :     case OMP_SECTIONS:
    6350            0 :     case OMP_ORDERED:
    6351            0 :     case OMP_CRITICAL:
    6352            0 :     case OMP_SINGLE:
    6353            0 :     case OMP_SECTION:
    6354            0 :     case OMP_MASTER:
    6355            0 :     case OMP_MASKED:
    6356            0 :     case OMP_TASKGROUP:
    6357            0 :     case OMP_TARGET_UPDATE:
    6358            0 :     case OMP_TARGET_ENTER_DATA:
    6359            0 :     case OMP_TARGET_EXIT_DATA:
    6360            0 :     case OMP_ATOMIC:
    6361            0 :     case OMP_ATOMIC_READ:
    6362            0 :     case OMP_ATOMIC_CAPTURE_OLD:
    6363            0 :     case OMP_ATOMIC_CAPTURE_NEW:
    6364            0 :     case OMP_DEPOBJ:
    6365            0 :     case OACC_PARALLEL:
    6366            0 :     case OACC_KERNELS:
    6367            0 :     case OACC_SERIAL:
    6368            0 :     case OACC_DATA:
    6369            0 :     case OACC_HOST_DATA:
    6370            0 :     case OACC_LOOP:
    6371            0 :     case OACC_CACHE:
    6372            0 :     case OACC_DECLARE:
    6373            0 :     case OACC_ENTER_DATA:
    6374            0 :     case OACC_EXIT_DATA:
    6375            0 :     case OACC_UPDATE:
    6376              :       /* GCC internal stuff.  */
    6377            0 :     case VA_ARG_EXPR:
    6378            0 :     case TRANSACTION_EXPR:
    6379            0 :     case AT_ENCODE_EXPR:
    6380              : 
    6381            0 :       if (flags & tf_error)
    6382            0 :         error_at (loc, "expression %qE is not a constant expression", t);
    6383              :       return false;
    6384              : 
    6385            0 :     case ASM_EXPR:
    6386            0 :       if (flags & tf_error)
    6387            0 :         inline_asm_in_constexpr_error (loc);
    6388              :       return false;
    6389              : 
    6390              :     case OBJ_TYPE_REF:
    6391              :       return true;
    6392              : 
    6393            0 :     case POINTER_DIFF_EXPR:
    6394            0 :     case MINUS_EXPR:
    6395            0 :       want_rval = true;
    6396            0 :       goto binary;
    6397              : 
    6398            0 :     case LT_EXPR:
    6399            0 :     case LE_EXPR:
    6400            0 :     case GT_EXPR:
    6401            0 :     case GE_EXPR:
    6402            0 :     case EQ_EXPR:
    6403            0 :     case NE_EXPR:
    6404            0 :     case SPACESHIP_EXPR:
    6405            0 :       want_rval = true;
    6406            0 :       goto binary;
    6407              : 
    6408            0 :     case PREINCREMENT_EXPR:
    6409            0 :     case POSTINCREMENT_EXPR:
    6410            0 :     case PREDECREMENT_EXPR:
    6411            0 :     case POSTDECREMENT_EXPR:
    6412            0 :       goto unary;
    6413              : 
    6414            0 :     case BIT_NOT_EXPR:
    6415              :       /* A destructor.  */
    6416            0 :       if (TYPE_P (TREE_OPERAND (t, 0)))
    6417              :         return true;
    6418              :       /* fall through.  */
    6419              : 
    6420            0 :     case CONJ_EXPR:
    6421            0 :     case SAVE_EXPR:
    6422            0 :     case FIX_TRUNC_EXPR:
    6423            0 :     case FLOAT_EXPR:
    6424            0 :     case NEGATE_EXPR:
    6425            0 :     case ABS_EXPR:
    6426            0 :     case ABSU_EXPR:
    6427            0 :     case TRUTH_NOT_EXPR:
    6428            0 :     case FIXED_CONVERT_EXPR:
    6429            0 :     case UNARY_PLUS_EXPR:
    6430            0 :     case UNARY_LEFT_FOLD_EXPR:
    6431            0 :     case UNARY_RIGHT_FOLD_EXPR:
    6432            0 :     unary:
    6433            0 :       return RECUR (TREE_OPERAND (t, 0), rval);
    6434              : 
    6435            0 :     case BIND_EXPR:
    6436            0 :       return RECUR (BIND_EXPR_BODY (t), want_rval);
    6437              : 
    6438            0 :     case CLEANUP_POINT_EXPR:
    6439            0 :     case EXPR_STMT:
    6440            0 :     case PAREN_EXPR:
    6441              :       /* For convenience.  */
    6442            0 :     case LOOP_EXPR:
    6443            0 :     case EXIT_EXPR:
    6444            0 :       return RECUR (TREE_OPERAND (t, 0), want_rval);
    6445              : 
    6446            0 :     case DECL_EXPR:
    6447            0 :       tmp = DECL_EXPR_DECL (t);
    6448            0 :       if (VAR_P (tmp) && !DECL_ARTIFICIAL (tmp))
    6449              :         {
    6450            0 :           if (RS_DECL_THREAD_LOCAL_P (tmp))
    6451              :             {
    6452            0 :               if (flags & tf_error)
    6453            0 :                 error_at (DECL_SOURCE_LOCATION (tmp),
    6454              :                           "%qD declared "
    6455              :                           "%<thread_local%> in %<constexpr%> context",
    6456              :                           tmp);
    6457              :               return false;
    6458              :             }
    6459            0 :           else if (TREE_STATIC (tmp))
    6460              :             {
    6461            0 :               if (flags & tf_error)
    6462            0 :                 error_at (DECL_SOURCE_LOCATION (tmp),
    6463              :                           "%qD declared "
    6464              :                           "%<static%> in %<constexpr%> context",
    6465              :                           tmp);
    6466              :               return false;
    6467              :             }
    6468            0 :           else if (!check_for_uninitialized_const_var (
    6469              :                      tmp, /*constexpr_context_p=*/true, flags))
    6470              :             return false;
    6471              :         }
    6472              :       return RECUR (tmp, want_rval);
    6473              : 
    6474            0 :     case TRY_FINALLY_EXPR:
    6475            0 :       return (RECUR (TREE_OPERAND (t, 0), want_rval)
    6476            0 :               && RECUR (TREE_OPERAND (t, 1), any));
    6477              : 
    6478            0 :     case SCOPE_REF:
    6479            0 :       return RECUR (TREE_OPERAND (t, 1), want_rval);
    6480              : 
    6481            0 :     case TARGET_EXPR:
    6482            0 :       if (!TARGET_EXPR_DIRECT_INIT_P (t) && !literal_type_p (TREE_TYPE (t)))
    6483              :         {
    6484            0 :           if (flags & tf_error)
    6485              :             {
    6486            0 :               auto_diagnostic_group d;
    6487            0 :               error_at (loc,
    6488              :                         "temporary of non-literal type %qT in a "
    6489              :                         "constant expression",
    6490            0 :                         TREE_TYPE (t));
    6491            0 :               explain_non_literal_class (TREE_TYPE (t));
    6492            0 :             }
    6493              :           return false;
    6494              :         }
    6495              :       /* FALLTHRU */
    6496            0 :     case INIT_EXPR:
    6497            0 :       return RECUR (TREE_OPERAND (t, 1), rval);
    6498              : 
    6499            0 :     case CONSTRUCTOR:
    6500            0 :       {
    6501            0 :         vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (t);
    6502            0 :         constructor_elt *ce;
    6503            0 :         for (i = 0; vec_safe_iterate (v, i, &ce); ++i)
    6504            0 :           if (!RECUR (ce->value, want_rval))
    6505              :             return false;
    6506              :         return true;
    6507              :       }
    6508              : 
    6509            0 :     case TREE_LIST:
    6510            0 :       {
    6511            0 :         gcc_assert (TREE_PURPOSE (t) == NULL_TREE || DECL_P (TREE_PURPOSE (t)));
    6512            0 :         if (!RECUR (TREE_VALUE (t), want_rval))
    6513              :           return false;
    6514            0 :         if (TREE_CHAIN (t) == NULL_TREE)
    6515              :           return true;
    6516            0 :         return RECUR (TREE_CHAIN (t), want_rval);
    6517              :       }
    6518              : 
    6519            0 :     case TRUNC_DIV_EXPR:
    6520            0 :     case CEIL_DIV_EXPR:
    6521            0 :     case FLOOR_DIV_EXPR:
    6522            0 :     case ROUND_DIV_EXPR:
    6523            0 :     case TRUNC_MOD_EXPR:
    6524            0 :     case CEIL_MOD_EXPR:
    6525            0 :     case ROUND_MOD_EXPR:
    6526            0 :       {
    6527            0 :         tree denom = TREE_OPERAND (t, 1);
    6528            0 :         if (!RECUR (denom, rval))
    6529              :           return false;
    6530              :         /* We can't call cxx_eval_outermost_constant_expr on an expression
    6531              :            that hasn't been through instantiate_non_dependent_expr yet.  */
    6532            0 :         denom = cxx_eval_outermost_constant_expr (denom, true);
    6533            0 :         if (integer_zerop (denom))
    6534              :           {
    6535            0 :             if (flags & tf_error)
    6536            0 :               error ("division by zero is not a constant expression");
    6537              :             return false;
    6538              :           }
    6539              :         else
    6540              :           {
    6541            0 :             want_rval = true;
    6542            0 :             return RECUR (TREE_OPERAND (t, 0), want_rval);
    6543              :           }
    6544              :       }
    6545              : 
    6546            0 :     case COMPOUND_EXPR:
    6547            0 :       {
    6548              :         /* check_return_expr sometimes wraps a TARGET_EXPR in a
    6549              :            COMPOUND_EXPR; don't get confused.  */
    6550            0 :         tree op0 = TREE_OPERAND (t, 0);
    6551            0 :         tree op1 = TREE_OPERAND (t, 1);
    6552            0 :         STRIP_NOPS (op1);
    6553            0 :         if (TREE_CODE (op0) == TARGET_EXPR && op1 == TARGET_EXPR_SLOT (op0))
    6554              :           return RECUR (op0, want_rval);
    6555              :         else
    6556            0 :           goto binary;
    6557              :       }
    6558              : 
    6559              :       /* If the first operand is the non-short-circuit constant, look at
    6560              :          the second operand; otherwise we only care about the first one for
    6561              :          potentiality.  */
    6562            0 :     case TRUTH_AND_EXPR:
    6563            0 :     case TRUTH_ANDIF_EXPR:
    6564            0 :       tmp = boolean_true_node;
    6565            0 :       goto truth;
    6566            0 :     case TRUTH_OR_EXPR:
    6567            0 :     case TRUTH_ORIF_EXPR:
    6568            0 :       tmp = boolean_false_node;
    6569            0 :     truth:
    6570            0 :       {
    6571            0 :         tree op0 = TREE_OPERAND (t, 0);
    6572            0 :         tree op1 = TREE_OPERAND (t, 1);
    6573            0 :         if (!RECUR (op0, rval))
    6574              :           return false;
    6575            0 :         if (!(flags & tf_error) && RECUR (op1, rval))
    6576              :           /* When quiet, try to avoid expensive trial evaluation by first
    6577              :              checking potentiality of the second operand.  */
    6578              :           return true;
    6579            0 :         op0 = cxx_eval_outermost_constant_expr (op0, true);
    6580            0 :         if (tree_int_cst_equal (op0, tmp))
    6581            0 :           return (flags & tf_error) ? RECUR (op1, rval) : false;
    6582              :         else
    6583              :           return true;
    6584              :       }
    6585              : 
    6586              :     case PLUS_EXPR:
    6587              :     case MULT_EXPR:
    6588              :     case POINTER_PLUS_EXPR:
    6589              :     case RDIV_EXPR:
    6590              :     case EXACT_DIV_EXPR:
    6591              :     case MIN_EXPR:
    6592              :     case MAX_EXPR:
    6593              :     case LSHIFT_EXPR:
    6594              :     case RSHIFT_EXPR:
    6595              :     case LROTATE_EXPR:
    6596              :     case RROTATE_EXPR:
    6597              :     case BIT_IOR_EXPR:
    6598              :     case BIT_XOR_EXPR:
    6599              :     case BIT_AND_EXPR:
    6600              :     case TRUTH_XOR_EXPR:
    6601              :     case UNORDERED_EXPR:
    6602              :     case ORDERED_EXPR:
    6603              :     case UNLT_EXPR:
    6604              :     case UNLE_EXPR:
    6605              :     case UNGT_EXPR:
    6606              :     case UNGE_EXPR:
    6607              :     case UNEQ_EXPR:
    6608              :     case LTGT_EXPR:
    6609              :     case RANGE_EXPR:
    6610              :     case COMPLEX_EXPR:
    6611            0 :       want_rval = true;
    6612              :       /* Fall through.  */
    6613            0 :     case ARRAY_REF:
    6614            0 :     case ARRAY_RANGE_REF:
    6615            0 :     case MEMBER_REF:
    6616            0 :     case DOTSTAR_EXPR:
    6617            0 :     case MEM_REF:
    6618            0 :     case BINARY_LEFT_FOLD_EXPR:
    6619            0 :     case BINARY_RIGHT_FOLD_EXPR:
    6620            0 :     binary:
    6621            0 :       for (i = 0; i < 2; ++i)
    6622            0 :         if (!RECUR (TREE_OPERAND (t, i), want_rval))
    6623              :           return false;
    6624              :       return true;
    6625              : 
    6626              :     case VEC_PERM_EXPR:
    6627            0 :       for (i = 0; i < 3; ++i)
    6628            0 :         if (!RECUR (TREE_OPERAND (t, i), true))
    6629              :           return false;
    6630              :       return true;
    6631              : 
    6632            0 :     case COND_EXPR:
    6633            0 :       if (COND_EXPR_IS_VEC_DELETE (t))
    6634              :         {
    6635            0 :           if (flags & tf_error)
    6636            0 :             error_at (loc, "%<delete[]%> is not a constant expression");
    6637              :           return false;
    6638              :         }
    6639              :       /* Fall through.  */
    6640            0 :     case IF_STMT:
    6641            0 :     case VEC_COND_EXPR:
    6642              :       /* If the condition is a known constant, we know which of the legs we
    6643              :          care about; otherwise we only require that the condition and
    6644              :          either of the legs be potentially constant.  */
    6645            0 :       tmp = TREE_OPERAND (t, 0);
    6646            0 :       if (!RECUR (tmp, rval))
    6647              :         return false;
    6648              : 
    6649            0 :       tmp = cxx_eval_outermost_constant_expr (tmp, true);
    6650              :       /* potential_constant_expression* isn't told if it is called for
    6651              :          manifestly_const_eval or not, so for consteval if always
    6652              :          process both branches as if the condition is not a known
    6653              :          constant.  */
    6654            0 :       if (TREE_CODE (t) != IF_STMT || !IF_STMT_CONSTEVAL_P (t))
    6655              :         {
    6656            0 :           if (integer_zerop (tmp))
    6657            0 :             return RECUR (TREE_OPERAND (t, 2), want_rval);
    6658            0 :           else if (TREE_CODE (tmp) == INTEGER_CST)
    6659            0 :             return RECUR (TREE_OPERAND (t, 1), want_rval);
    6660              :         }
    6661            0 :       tmp = *jump_target;
    6662            0 :       for (i = 1; i < 3; ++i)
    6663              :         {
    6664            0 :           tree this_jump_target = tmp;
    6665            0 :           if (potential_constant_expression_1 (TREE_OPERAND (t, i), want_rval,
    6666              :                                                strict, now, tf_none,
    6667              :                                                &this_jump_target))
    6668              :             {
    6669            0 :               if (returns (&this_jump_target))
    6670            0 :                 *jump_target = this_jump_target;
    6671            0 :               else if (!returns (jump_target))
    6672              :                 {
    6673            0 :                   if (breaks (&this_jump_target)
    6674            0 :                       || continues (&this_jump_target))
    6675            0 :                     *jump_target = this_jump_target;
    6676            0 :                   if (i == 1)
    6677              :                     {
    6678              :                       /* If the then branch is potentially constant, but
    6679              :                          does not return, check if the else branch
    6680              :                          couldn't return, break or continue.  */
    6681            0 :                       hash_set<tree> pset;
    6682            0 :                       check_for_return_continue_data data
    6683            0 :                         = {&pset, NULL_TREE, NULL_TREE};
    6684            0 :                       if (tree ret_expr
    6685            0 :                           = rs_walk_tree (&TREE_OPERAND (t, 2),
    6686              :                                           check_for_return_continue, &data,
    6687              :                                           &pset))
    6688            0 :                         *jump_target = ret_expr;
    6689            0 :                       else if (*jump_target == NULL_TREE)
    6690              :                         {
    6691            0 :                           if (data.continue_stmt)
    6692            0 :                             *jump_target = data.continue_stmt;
    6693            0 :                           else if (data.break_stmt)
    6694            0 :                             *jump_target = data.break_stmt;
    6695              :                         }
    6696            0 :                     }
    6697              :                 }
    6698            0 :               return true;
    6699              :             }
    6700              :         }
    6701            0 :       if (flags & tf_error)
    6702            0 :         error_at (loc, "expression %qE is not a constant expression", t);
    6703              :       return false;
    6704              : 
    6705              :     case TYPE_DECL:
    6706              :       /* We can see these in statement-expressions.  */
    6707              :       return true;
    6708              : 
    6709            0 :     case GOTO_EXPR:
    6710            0 :       {
    6711            0 :         tree *target = &TREE_OPERAND (t, 0);
    6712            0 :         if (breaks (target) || continues (target) || returns (target))
    6713              :           {
    6714            0 :             *jump_target = *target;
    6715            0 :             return true;
    6716              :           }
    6717            0 :         if (TREE_CODE (*target) == LABEL_DECL && DECL_ARTIFICIAL (*target))
    6718              :           return true;
    6719            0 :         if (flags & tf_error)
    6720            0 :           error_at (loc, "%<goto%> is not a constant expression");
    6721              :         return false;
    6722              :       }
    6723              : 
    6724            0 :     case LABEL_EXPR:
    6725            0 :       t = LABEL_EXPR_LABEL (t);
    6726            0 :       if (DECL_ARTIFICIAL (t))
    6727              :         return true;
    6728            0 :       else if (flags & tf_error)
    6729            0 :         error_at (loc, "label definition in %<constexpr%> function only "
    6730              :                        "available with %<-std=c++2b%> or %<-std=gnu++2b%>");
    6731              :       return false;
    6732              : 
    6733            0 :     case ANNOTATE_EXPR:
    6734            0 :       return RECUR (TREE_OPERAND (t, 0), rval);
    6735              : 
    6736            0 :     case BIT_CAST_EXPR:
    6737            0 :       return RECUR (TREE_OPERAND (t, 0), rval);
    6738              : 
    6739            0 :     default:
    6740            0 :       sorry ("unexpected AST of kind %s", get_tree_code_name (TREE_CODE (t)));
    6741            0 :       rust_unreachable ();
    6742              :       return false;
    6743              :     }
    6744              : #undef RECUR
    6745              : }
    6746              : 
    6747              : bool
    6748            0 : potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
    6749              :                                  tsubst_flags_t flags)
    6750              : {
    6751            0 :   if (flags & tf_error)
    6752              :     {
    6753              :       /* Check potentiality quietly first, as that could be performed more
    6754              :          efficiently in some cases (currently only for TRUTH_*_EXPR).  If
    6755              :          that fails, replay the check noisily to give errors.  */
    6756            0 :       flags &= ~tf_error;
    6757            0 :       if (potential_constant_expression_1 (t, want_rval, strict, now, flags))
    6758              :         return true;
    6759            0 :       flags |= tf_error;
    6760              :     }
    6761              : 
    6762            0 :   tree target = NULL_TREE;
    6763            0 :   return potential_constant_expression_1 (t, want_rval, strict, now, flags,
    6764            0 :                                           &target);
    6765              : }
    6766              : 
    6767              : // forked from gcc/cp/constexpr.cc fold_non_dependent_init
    6768              : 
    6769              : /* Like maybe_constant_init but first fully instantiate the argument.  */
    6770              : 
    6771              : tree
    6772            0 : fold_non_dependent_init (tree t, tsubst_flags_t /*=tf_warning_or_error*/,
    6773              :                          bool manifestly_const_eval /*=false*/,
    6774              :                          tree object /* = NULL_TREE */)
    6775              : {
    6776            0 :   if (t == NULL_TREE)
    6777              :     return NULL_TREE;
    6778              : 
    6779            0 :   return maybe_constant_init (t, object, manifestly_const_eval);
    6780              : }
    6781              : 
    6782              : /* Check whether the shift operation with code CODE and type TYPE on LHS
    6783              :    and RHS is undefined.  If it is, give an error with an explanation,
    6784              :    and return true; return false otherwise.  */
    6785              : 
    6786              : static bool
    6787          346 : eval_check_shift_p (location_t loc, const constexpr_ctx *ctx,
    6788              :                     enum tree_code code, tree type, tree lhs, tree rhs)
    6789              : {
    6790          346 :   if ((code != LSHIFT_EXPR && code != RSHIFT_EXPR)
    6791            2 :       || TREE_CODE (lhs) != INTEGER_CST || TREE_CODE (rhs) != INTEGER_CST)
    6792              :     return false;
    6793              : 
    6794            2 :   tree lhstype = TREE_TYPE (lhs);
    6795            2 :   unsigned HOST_WIDE_INT uprec = TYPE_PRECISION (TREE_TYPE (lhs));
    6796              : 
    6797              :   /* [expr.shift] The behavior is undefined if the right operand
    6798              :      is negative, or greater than or equal to the length in bits
    6799              :      of the promoted left operand.  */
    6800            2 :   if (tree_int_cst_sgn (rhs) == -1)
    6801              :     {
    6802            0 :       if (!ctx->quiet)
    6803            0 :         permerror (loc, "right operand of shift expression %q+E is negative",
    6804              :                    build2_loc (loc, code, type, lhs, rhs));
    6805            0 :       return (!flag_permissive || ctx->quiet);
    6806              :     }
    6807            2 :   if (compare_tree_int (rhs, uprec) >= 0)
    6808              :     {
    6809            0 :       if (!ctx->quiet)
    6810            0 :         permerror (loc,
    6811              :                    "right operand of shift expression %q+E is greater "
    6812              :                    "than or equal to the precision %wu of the left operand",
    6813              :                    build2_loc (loc, code, type, lhs, rhs), uprec);
    6814            0 :       return (!flag_permissive || ctx->quiet);
    6815              :     }
    6816              : 
    6817              :   /* The value of E1 << E2 is E1 left-shifted E2 bit positions; [...]
    6818              :      if E1 has a signed type and non-negative value, and E1x2^E2 is
    6819              :      representable in the corresponding unsigned type of the result type,
    6820              :      then that value, converted to the result type, is the resulting value;
    6821              :      otherwise, the behavior is undefined.
    6822              :      For C++20:
    6823              :      The value of E1 << E2 is the unique value congruent to E1 x 2^E2 modulo
    6824              :      2^N, where N is the range exponent of the type of the result.  */
    6825            2 :   if (code == LSHIFT_EXPR && !TYPE_OVERFLOW_WRAPS (lhstype))
    6826              :     {
    6827            0 :       if (tree_int_cst_sgn (lhs) == -1)
    6828              :         {
    6829            0 :           if (!ctx->quiet)
    6830            0 :             permerror (loc, "left operand of shift expression %q+E is negative",
    6831              :                        build2_loc (loc, code, type, lhs, rhs));
    6832            0 :           return (!flag_permissive || ctx->quiet);
    6833              :         }
    6834              :       /* For signed x << y the following:
    6835              :          (unsigned) x >> ((prec (lhs) - 1) - y)
    6836              :          if > 1, is undefined.  The right-hand side of this formula
    6837              :          is the highest bit of the LHS that can be set (starting from 0),
    6838              :          so that the shift doesn't overflow.  We then right-shift the LHS
    6839              :          to see whether any other bit is set making the original shift
    6840              :          undefined -- the result is not representable in the corresponding
    6841              :          unsigned type.  */
    6842            0 :       tree t = build_int_cst (unsigned_type_node, uprec - 1);
    6843            0 :       t = fold_build2 (MINUS_EXPR, unsigned_type_node, t, rhs);
    6844            0 :       tree ulhs = fold_convert (unsigned_type_for (lhstype), lhs);
    6845            0 :       t = fold_build2 (RSHIFT_EXPR, TREE_TYPE (ulhs), ulhs, t);
    6846            0 :       if (tree_int_cst_lt (integer_one_node, t))
    6847              :         {
    6848            0 :           if (!ctx->quiet)
    6849            0 :             permerror (loc, "shift expression %q+E overflows",
    6850              :                        build2_loc (loc, code, type, lhs, rhs));
    6851            0 :           return (!flag_permissive || ctx->quiet);
    6852              :         }
    6853              :     }
    6854              :   return false;
    6855              : }
    6856              : 
    6857              : /* Rust rejects arithmetic overflow during constant evaluation for both signed
    6858              :    and unsigned types, unlike C where unsigned wraparound is well defined, so
    6859              :    TREE_OVERFLOW alone is not enough: GCC only sets it for signed operations.
    6860              : 
    6861              :    Operations built in a constant context are left unfolded by
    6862              :    Backend::arithmetic_or_logical_expression, so that we still see the
    6863              :    operation and its operands here rather than an INTEGER_CST which would
    6864              :    carry neither a location nor, for unsigned types, any trace of the
    6865              :    overflow.
    6866              : 
    6867              :    Returns true when the operation overflows, in which case the expression is
    6868              :    not a constant.  */
    6869              : 
    6870              : static bool
    6871          346 : eval_check_overflow_p (location_t loc, const constexpr_ctx *ctx,
    6872              :                        enum tree_code code, tree type, tree lhs, tree rhs)
    6873              : {
    6874          346 :   if ((code != PLUS_EXPR && code != MINUS_EXPR && code != MULT_EXPR)
    6875          313 :       || TREE_CODE (lhs) != INTEGER_CST || TREE_CODE (rhs) != INTEGER_CST
    6876          299 :       || !INTEGRAL_TYPE_P (type)
    6877          299 :       || TYPE_PRECISION (TREE_TYPE (lhs)) != TYPE_PRECISION (type)
    6878          645 :       || TYPE_PRECISION (TREE_TYPE (rhs)) != TYPE_PRECISION (type))
    6879              :     return false;
    6880              : 
    6881              :   /* Note we deliberately do not check TYPE_OVERFLOW_WRAPS here: it is set for
    6882              :      unsigned types because wrapping is defined in C, but Rust rejects it.  */
    6883          299 :   signop sgn = TYPE_SIGN (type);
    6884          299 :   wide_int lw = wi::to_wide (lhs);
    6885          299 :   wide_int rw = wi::to_wide (rhs);
    6886          299 :   wi::overflow_type ovf = wi::OVF_NONE;
    6887              : 
    6888          299 :   switch (code)
    6889              :     {
    6890          188 :     case PLUS_EXPR:
    6891          188 :       wi::add (lw, rw, sgn, &ovf);
    6892          188 :       break;
    6893            2 :     case MINUS_EXPR:
    6894            2 :       wi::sub (lw, rw, sgn, &ovf);
    6895            2 :       break;
    6896          109 :     case MULT_EXPR:
    6897          109 :       wi::mul (lw, rw, sgn, &ovf);
    6898          109 :       break;
    6899              :     default:
    6900              :       gcc_unreachable ();
    6901              :     }
    6902              : 
    6903          299 :   if (ovf == wi::OVF_NONE)
    6904              :     return false;
    6905              : 
    6906              :   /* Unlike the shift checks above this is a hard error, not a permerror:
    6907              :      overflow in a constant is always rejected by Rust.  */
    6908           11 :   if (!ctx->quiet)
    6909              :     {
    6910           11 :       char *expr_str
    6911           11 :         = print_generic_expr_to_str (build2_loc (loc, code, type, lhs, rhs));
    6912           11 :       rust_error_at (loc, ErrorCode::E0080,
    6913              :                      "attempt to compute %qs, which would overflow", expr_str);
    6914           11 :       free (expr_str);
    6915              :     }
    6916              : 
    6917              :   return true;
    6918          299 : }
    6919              : 
    6920              : /* Helper function for cxx_eval_binary_expression.  Try to optimize
    6921              :    original POINTER_PLUS_EXPR T, LHS p+ RHS, return NULL_TREE if the
    6922              :    generic folding should be used.  */
    6923              : 
    6924              : static tree
    6925            0 : fold_pointer_plus_expression (const constexpr_ctx *ctx, tree t, tree lhs,
    6926              :                               tree rhs, bool *non_constant_p, bool *overflow_p,
    6927              :                               tree *jump_target)
    6928              : {
    6929            0 :   STRIP_NOPS (lhs);
    6930            0 :   if (TREE_CODE (lhs) != ADDR_EXPR)
    6931              :     return NULL_TREE;
    6932              : 
    6933            0 :   lhs = TREE_OPERAND (lhs, 0);
    6934              : 
    6935              :   /* &A[i] p+ j => &A[i + j] */
    6936            0 :   if (TREE_CODE (lhs) == ARRAY_REF
    6937            0 :       && TREE_CODE (TREE_OPERAND (lhs, 1)) == INTEGER_CST
    6938            0 :       && TREE_CODE (rhs) == INTEGER_CST && TYPE_SIZE_UNIT (TREE_TYPE (lhs))
    6939            0 :       && TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (lhs))) == INTEGER_CST)
    6940              :     {
    6941            0 :       tree orig_type = TREE_TYPE (t);
    6942            0 :       location_t loc = EXPR_LOCATION (t);
    6943            0 :       tree type = TREE_TYPE (lhs);
    6944              : 
    6945            0 :       t = fold_convert_loc (loc, ssizetype, TREE_OPERAND (lhs, 1));
    6946            0 :       tree nelts = array_type_nelts_top (TREE_TYPE (TREE_OPERAND (lhs, 0)));
    6947            0 :       nelts = eval_constant_expression (ctx, nelts, true, non_constant_p,
    6948              :                                         overflow_p, jump_target);
    6949            0 :       if (*non_constant_p)
    6950              :         return NULL_TREE;
    6951            0 :       if (*jump_target)
    6952              :         return NULL_TREE;
    6953              :       /* Don't fold an out-of-bound access.  */
    6954            0 :       if (!tree_int_cst_le (t, nelts))
    6955              :         return NULL_TREE;
    6956            0 :       rhs = fold_convert (ssizetype, rhs);
    6957              :       /* Don't fold if rhs can't be divided exactly by TYPE_SIZE_UNIT.
    6958              :          constexpr int A[1]; ... (char *)&A[0] + 1 */
    6959            0 :       if (!integer_zerop (fold_build2_loc (loc, TRUNC_MOD_EXPR, sizetype, rhs,
    6960            0 :                                            TYPE_SIZE_UNIT (type))))
    6961              :         return NULL_TREE;
    6962              :       /* Make sure to treat the second operand of POINTER_PLUS_EXPR
    6963              :          as signed.  */
    6964            0 :       rhs = fold_build2_loc (loc, EXACT_DIV_EXPR, ssizetype, rhs,
    6965            0 :                              TYPE_SIZE_UNIT (type));
    6966            0 :       t = size_binop_loc (loc, PLUS_EXPR, rhs, t);
    6967            0 :       t = build4_loc (loc, ARRAY_REF, type, TREE_OPERAND (lhs, 0), t, NULL_TREE,
    6968              :                       NULL_TREE);
    6969            0 :       t = build_fold_addr_expr (t);
    6970            0 :       t = fold_convert (orig_type, t);
    6971            0 :       return eval_constant_expression (ctx, t, true, non_constant_p, overflow_p,
    6972            0 :                                        jump_target);
    6973              :     }
    6974              : 
    6975              :   return NULL_TREE;
    6976              : }
    6977              : 
    6978              : /* Try to fold expressions like
    6979              :    (struct S *) (&a[0].D.2378 + 12)
    6980              :    into
    6981              :    &MEM <struct T> [(void *)&a + 12B]
    6982              :    This is something normally done by gimple_fold_stmt_to_constant_1
    6983              :    on GIMPLE, but is undesirable on GENERIC if we are e.g. going to
    6984              :    dereference the address because some details are lost.
    6985              :    For pointer comparisons we want such folding though so that
    6986              :    match.pd address_compare optimization works.  */
    6987              : 
    6988              : static tree
    6989            2 : maybe_fold_addr_pointer_plus (tree t)
    6990              : {
    6991            2 :   while (CONVERT_EXPR_P (t) && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (t, 0))))
    6992            0 :     t = TREE_OPERAND (t, 0);
    6993            2 :   if (TREE_CODE (t) != POINTER_PLUS_EXPR)
    6994              :     return NULL_TREE;
    6995            0 :   tree op0 = TREE_OPERAND (t, 0);
    6996            0 :   tree op1 = TREE_OPERAND (t, 1);
    6997            0 :   if (TREE_CODE (op1) != INTEGER_CST)
    6998              :     return NULL_TREE;
    6999            0 :   while (CONVERT_EXPR_P (op0)
    7000            0 :          && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (op0, 0))))
    7001            0 :     op0 = TREE_OPERAND (op0, 0);
    7002            0 :   if (TREE_CODE (op0) != ADDR_EXPR)
    7003              :     return NULL_TREE;
    7004            0 :   op1 = fold_convert (ptr_type_node, op1);
    7005            0 :   tree r = fold_build2 (MEM_REF, TREE_TYPE (TREE_TYPE (op0)), op0, op1);
    7006            0 :   return build1_loc (EXPR_LOCATION (t), ADDR_EXPR, TREE_TYPE (op0), r);
    7007              : }
    7008              : 
    7009              : static tree
    7010            2 : maybe_fold_reference_address_to_pointer (tree t)
    7011              : {
    7012            2 :   if (!CONVERT_EXPR_P (t) || !POINTER_TYPE_P (TREE_TYPE (t)))
    7013              :     return t;
    7014              : 
    7015            2 :   tree op = TREE_OPERAND (t, 0);
    7016            2 :   if (TREE_CODE (op) != ADDR_EXPR || !TYPE_REF_P (TREE_TYPE (op)))
    7017              :     return t;
    7018              : 
    7019            2 :   return build_fold_addr_expr_with_type_loc (EXPR_LOCATION (t),
    7020            2 :                                              TREE_OPERAND (op, 0),
    7021            4 :                                              TREE_TYPE (t));
    7022              : }
    7023              : 
    7024              : } // namespace Compile
    7025              : } // namespace Rust
    7026              : 
    7027              : using namespace Rust::Compile;
    7028              : 
    7029              : #include "gt-rust-rust-constexpr.h"
        

Generated by: LCOV version 2.5.0-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.