[clang] 6b48d20 - [clang][AST] Improve diagnostic for `nullptr` constexpr function pointer call
Aaron Ballman via cfe-commits
cfe-commits at lists.llvm.org
Mon Mar 13 09:54:59 PDT 2023
Author: Takuya Shimizu
Date: 2023-03-13T12:53:12-04:00
New Revision: 6b48d202ef497f4d512c382fe0db8c5ad3a72faa
URL: https://github.com/llvm/llvm-project/commit/6b48d202ef497f4d512c382fe0db8c5ad3a72faa
DIFF: https://github.com/llvm/llvm-project/commit/6b48d202ef497f4d512c382fe0db8c5ad3a72faa.diff
LOG: [clang][AST] Improve diagnostic for `nullptr` constexpr function pointer call
This patch improves diagnostic for clang constexpr evaluator by adding
a check for nullptr in function pointer call evaluations.
ex.
```
constexpr int foo(int (*bla)(void)) {
return bla();
}
static_assert(foo(nullptr) == 1);
```
BEFORE this patch, clang generates the following diagnostic for the
code above:
```
<source>:5:15: error: static assertion expression is not an integral constant expression
static_assert(foo(nullptr) == 1);
^~~~~~~~~~~~~~~~~
<source>:2:10: note: subexpression not valid in a constant expression
return bla();
^
<source>:5:15: note: in call to 'foo(nullptr)'
static_assert(foo(nullptr) == 1);
^
1 error generated.
```
AFTER this patch, subexpression not valid in a constant expression note
is replaced with 'bla' evaluates to a null function pointer.
Fixes https://github.com/llvm/llvm-project/issues/59872
Differential Revision: https://reviews.llvm.org/D145793
Added:
Modified:
clang/docs/ReleaseNotes.rst
clang/include/clang/Basic/DiagnosticASTKinds.td
clang/lib/AST/ExprConstant.cpp
clang/test/SemaCXX/constant-expression-cxx11.cpp
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 440fd04274777..a8c6f2f733d78 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -165,6 +165,8 @@ Improvements to Clang's diagnostics
- Diagnostics relating to macros on the command line of a preprocessed assembly
file are now reported as coming from the file ``<command line>`` instead of
``<built-in>``.
+- Clang constexpr evaluator now provides a more concise diagnostic when calling
+ function pointer that is known to be null.
Bug Fixes in This Version
-------------------------
diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td
index 28120d13fd9e7..c283ee842e730 100644
--- a/clang/include/clang/Basic/DiagnosticASTKinds.td
+++ b/clang/include/clang/Basic/DiagnosticASTKinds.td
@@ -127,6 +127,8 @@ def note_constexpr_null_subobject : Note<
"access array element of|perform pointer arithmetic on|"
"access real component of|"
"access imaginary component of}0 null pointer">;
+def note_constexpr_null_callee : Note<
+ "'%0' evaluates to a null function pointer">;
def note_constexpr_function_param_value_unknown : Note<
"function parameter %0 with unknown value cannot be used in a constant "
"expression">;
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 26c23423b858f..fbe92d054d6bc 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -7668,6 +7668,11 @@ class ExprEvaluatorBase
if (!CalleeLV.getLValueOffset().isZero())
return Error(Callee);
+ if (CalleeLV.isNullPointer()) {
+ Info.FFDiag(Callee, diag::note_constexpr_null_callee)
+ << const_cast<Expr *>(Callee);
+ return false;
+ }
FD = dyn_cast_or_null<FunctionDecl>(
CalleeLV.getLValueBase().dyn_cast<const ValueDecl *>());
if (!FD)
diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp
index fea45d56f0fd3..5e7a80c81eaee 100644
--- a/clang/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp
@@ -279,7 +279,7 @@ namespace FunctionPointers {
constexpr auto Select(int n) -> int (*)(int) {
return n == 2 ? &Double : n == 3 ? &Triple : n == 4 ? &Quadruple : 0;
}
- constexpr int Apply(int (*F)(int), int n) { return F(n); } // expected-note {{subexpression}}
+ constexpr int Apply(int (*F)(int), int n) { return F(n); } // expected-note {{'F' evaluates to a null function pointer}}
static_assert(1 + Apply(Select(4), 5) + Apply(Select(3), 7) == 42, "");
More information about the cfe-commits
mailing list