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