aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/constexpr.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/constexpr.c')
-rw-r--r--gcc/cp/constexpr.c48
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