aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/constexpr.cc
diff options
context:
space:
mode:
authorNathaniel Shead <nathanieloshead@gmail.com>2023-12-17 12:46:02 +1100
committerNathaniel Shead <nathanieloshead@gmail.com>2023-12-20 08:18:56 +1100
commit5ba949c096f5250aa4efb94fb7c94d1304c1bf39 (patch)
tree9b29b2f3ac81eafcfdd9dfe5fd0d2a984350abfe /gcc/cp/constexpr.cc
parentd31c54c7da7661a964de59765fa8e7938796cc86 (diff)
downloadgcc-5ba949c096f5250aa4efb94fb7c94d1304c1bf39.zip
gcc-5ba949c096f5250aa4efb94fb7c94d1304c1bf39.tar.gz
gcc-5ba949c096f5250aa4efb94fb7c94d1304c1bf39.tar.bz2
c++: Check null pointer deref when calling memfn in constexpr [PR102420]
Calling a non-static member function on a null pointer is undefined behaviour (see [expr.ref] p8) and should error in constant evaluation, even if the 'this' pointer is never actually accessed within that function. One catch is that currently, the function pointer conversion operator for lambdas passes a null pointer as the 'this' pointer to the underlying 'operator()', so for now we ignore such calls. PR c++/102420 gcc/cp/ChangeLog: * constexpr.cc (cxx_bind_parameters_in_call): Check for calling non-static member functions with a null pointer. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/constexpr-memfn2.C: New test. Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com>
Diffstat (limited to 'gcc/cp/constexpr.cc')
-rw-r--r--gcc/cp/constexpr.cc14
1 files changed, 14 insertions, 0 deletions
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 051f73f..eff43a4 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -1884,6 +1884,20 @@ cxx_bind_parameters_in_call (const constexpr_ctx *ctx, tree t, tree fun,
TARGET_EXPR, and use its CONSTRUCTOR as the value of the parm. */
arg = cxx_eval_constant_expression (ctx, x, vc_prvalue,
non_constant_p, overflow_p);
+ /* Check we aren't dereferencing a null pointer when calling a non-static
+ member function, which is undefined behaviour. */
+ if (i == 0 && DECL_NONSTATIC_MEMBER_FUNCTION_P (fun)
+ && integer_zerop (arg)
+ /* But ignore calls from within compiler-generated code, to handle
+ cases like lambda function pointer conversion operator thunks
+ which pass NULL as the 'this' pointer. */
+ && !(TREE_CODE (t) == CALL_EXPR && CALL_FROM_THUNK_P (t)))
+ {
+ if (!ctx->quiet)
+ error_at (cp_expr_loc_or_input_loc (x),
+ "dereferencing a null pointer");
+ *non_constant_p = true;
+ }
/* Don't VERIFY_CONSTANT here. */
if (*non_constant_p && ctx->quiet)
break;