diff --git a/clang/lib/AST/Interp/FunctionPointer.h b/clang/lib/AST/Interp/FunctionPointer.h index 4a3f993d4882e2..bb3da9b50aa552 100644 --- a/clang/lib/AST/Interp/FunctionPointer.h +++ b/clang/lib/AST/Interp/FunctionPointer.h @@ -26,6 +26,7 @@ class FunctionPointer final { FunctionPointer(const Function *Func) : Func(Func) { assert(Func); } const Function *getFunction() const { return Func; } + bool isZero() const { return !Func; } APValue toAPValue() const { if (!Func) diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index 23a2756a18f690..d885d19ce7064f 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -2087,6 +2087,12 @@ inline bool CallPtr(InterpState &S, CodePtr OpPC, uint32_t ArgSize) { const FunctionPointer &FuncPtr = S.Stk.pop(); const Function *F = FuncPtr.getFunction(); + if (!F) { + const Expr *E = S.Current->getExpr(OpPC); + S.FFDiag(E, diag::note_constexpr_null_callee) + << const_cast(E) << E->getSourceRange(); + return false; + } assert(F); assert(ArgSize >= F->getWrittenArgSize()); diff --git a/clang/test/AST/Interp/functions.cpp b/clang/test/AST/Interp/functions.cpp index 51269741eb9018..9daf8722050f07 100644 --- a/clang/test/AST/Interp/functions.cpp +++ b/clang/test/AST/Interp/functions.cpp @@ -123,9 +123,12 @@ namespace FunctionPointers { } constexpr int applyBinOp(int a, int b, int (*op)(int, int)) { - return op(a, b); + return op(a, b); // both-note {{evaluates to a null function pointer}} } static_assert(applyBinOp(1, 2, add) == 3, ""); + static_assert(applyBinOp(1, 2, nullptr) == 3, ""); // both-error {{not an integral constant expression}} \ + // both-note {{in call to}} + constexpr int ignoreReturnValue() { int (*foo)(int, int) = add;