diff options
Diffstat (limited to 'gcc/cp/constexpr.c')
-rw-r--r-- | gcc/cp/constexpr.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index f766abd..1939166 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -2129,6 +2129,52 @@ replace_result_decl (tree *tp, tree decl, tree replacement) return data.changed; } +/* Evaluate the call T to virtual function thunk THUNK_FNDECL. */ + +static tree +cxx_eval_thunk_call (const constexpr_ctx *ctx, tree t, tree thunk_fndecl, + bool lval, + bool *non_constant_p, bool *overflow_p) +{ + tree function = THUNK_TARGET (thunk_fndecl); + + /* virtual_offset is only set in the presence of virtual bases, which make + the class non-literal, so we don't need to handle it here. */ + if (THUNK_VIRTUAL_OFFSET (thunk_fndecl)) + { + gcc_assert (!DECL_DECLARED_CONSTEXPR_P (function)); + if (!ctx->quiet) + { + error ("call to non-%<constexpr%> function %qD", function); + explain_invalid_constexpr_fn (function); + } + *non_constant_p = true; + return t; + } + + tree new_call = copy_node (t); + CALL_EXPR_FN (new_call) = function; + TREE_TYPE (new_call) = TREE_TYPE (TREE_TYPE (function)); + + tree offset = size_int (THUNK_FIXED_OFFSET (thunk_fndecl)); + + if (DECL_THIS_THUNK_P (thunk_fndecl)) + { + /* 'this'-adjusting thunk. */ + tree this_arg = CALL_EXPR_ARG (t, 0); + this_arg = build2 (POINTER_PLUS_EXPR, TREE_TYPE (this_arg), + this_arg, offset); + CALL_EXPR_ARG (new_call, 0) = this_arg; + } + else + /* Return-adjusting thunk. */ + new_call = build2 (POINTER_PLUS_EXPR, TREE_TYPE (new_call), + new_call, offset); + + return cxx_eval_constant_expression (ctx, new_call, lval, + non_constant_p, overflow_p); +} + /* Subroutine of cxx_eval_constant_expression. Evaluate the call expression tree T in the context of OLD_CALL expression evaluation. */ @@ -2209,6 +2255,8 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, if (fndecl_built_in_p (fun)) return cxx_eval_builtin_function_call (ctx, t, fun, lval, non_constant_p, overflow_p); + if (DECL_THUNK_P (fun)) + return cxx_eval_thunk_call (ctx, t, fun, lval, non_constant_p, overflow_p); if (!DECL_DECLARED_CONSTEXPR_P (fun)) { if (TREE_CODE (t) == CALL_EXPR |