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

Generated by: LCOV version 2.4-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.