[gcc r14-6722] c++: Check null pointer deref when calling memfn in constexpr [PR102420]
Nathaniel Shead
nshead@gcc.gnu.org
Tue Dec 19 21:19:25 GMT 2023
https://gcc.gnu.org/g:5ba949c096f5250aa4efb94fb7c94d1304c1bf39
commit r14-6722-g5ba949c096f5250aa4efb94fb7c94d1304c1bf39
Author: Nathaniel Shead <nathanieloshead@gmail.com>
Date: Sun Dec 17 12:46:02 2023 +1100
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>
Diff:
---
gcc/cp/constexpr.cc | 14 ++++++++++++++
gcc/testsuite/g++.dg/cpp0x/constexpr-memfn2.C | 10 ++++++++++
2 files changed, 24 insertions(+)
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 051f73fb73f..eff43a42353 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;
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-memfn2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-memfn2.C
new file mode 100644
index 00000000000..dde9416d86f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-memfn2.C
@@ -0,0 +1,10 @@
+// PR c++/102420
+// { dg-do compile { target c++11 } }
+
+struct X {
+ constexpr int f() { return 0; }
+};
+constexpr int g(X* x) {
+ return x->f(); // { dg-error "dereferencing a null pointer" }
+}
+constexpr int t = g(nullptr); // { dg-message "in .constexpr. expansion" }
More information about the Gcc-cvs
mailing list