[clang] f8a9c55 - [clang][Interp] Emit diagnostic when comparing function pointers
Timm Bäder via cfe-commits
cfe-commits at lists.llvm.org
Thu Apr 27 03:33:44 PDT 2023
Author: Timm Bäder
Date: 2023-04-27T12:33:28+02:00
New Revision: f8a9c55bef380a592c4588025f8b6ca4dfc94c47
URL: https://github.com/llvm/llvm-project/commit/f8a9c55bef380a592c4588025f8b6ca4dfc94c47
DIFF: https://github.com/llvm/llvm-project/commit/f8a9c55bef380a592c4588025f8b6ca4dfc94c47.diff
LOG: [clang][Interp] Emit diagnostic when comparing function pointers
Function pointers can be compared for (in)equality but, but LE, GE, LT,
and GT opcodes should emit an error and abort.
Differential Revision: https://reviews.llvm.org/D149154
Added:
Modified:
clang/lib/AST/Interp/FunctionPointer.h
clang/lib/AST/Interp/Interp.h
clang/lib/AST/Interp/Opcodes.td
clang/test/AST/Interp/functions.cpp
Removed:
################################################################################
diff --git a/clang/lib/AST/Interp/FunctionPointer.h b/clang/lib/AST/Interp/FunctionPointer.h
index 2d449bdb031d..20d4d7793185 100644
--- a/clang/lib/AST/Interp/FunctionPointer.h
+++ b/clang/lib/AST/Interp/FunctionPointer.h
@@ -8,6 +8,7 @@
#include "clang/AST/APValue.h"
namespace clang {
+class ASTContext;
namespace interp {
class FunctionPointer final {
@@ -38,6 +39,13 @@ class FunctionPointer final {
OS << ")";
}
+ std::string toDiagnosticString(const ASTContext &Ctx) const {
+ if (!Func)
+ return "nullptr";
+
+ return toAPValue().getAsString(Ctx, Func->getDecl()->getType());
+ }
+
ComparisonCategoryResult compare(const FunctionPointer &RHS) const {
if (Func == RHS.Func)
return ComparisonCategoryResult::Equal;
diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h
index 7b80bb964991..d751ba021b11 100644
--- a/clang/lib/AST/Interp/Interp.h
+++ b/clang/lib/AST/Interp/Interp.h
@@ -574,6 +574,29 @@ bool CmpHelperEQ(InterpState &S, CodePtr OpPC, CompareFn Fn) {
return CmpHelper<T>(S, OpPC, Fn);
}
+/// Function pointers cannot be compared in an ordered way.
+template <>
+inline bool CmpHelper<FunctionPointer>(InterpState &S, CodePtr OpPC,
+ CompareFn Fn) {
+ const auto &RHS = S.Stk.pop<FunctionPointer>();
+ const auto &LHS = S.Stk.pop<FunctionPointer>();
+
+ const SourceInfo &Loc = S.Current->getSource(OpPC);
+ S.FFDiag(Loc, diag::note_constexpr_pointer_comparison_unspecified)
+ << LHS.toDiagnosticString(S.getCtx())
+ << RHS.toDiagnosticString(S.getCtx());
+ return false;
+}
+
+template <>
+inline bool CmpHelperEQ<FunctionPointer>(InterpState &S, CodePtr OpPC,
+ CompareFn Fn) {
+ const auto &RHS = S.Stk.pop<FunctionPointer>();
+ const auto &LHS = S.Stk.pop<FunctionPointer>();
+ S.Stk.push<Boolean>(Boolean::from(Fn(LHS.compare(RHS))));
+ return true;
+}
+
template <>
inline bool CmpHelper<Pointer>(InterpState &S, CodePtr OpPC, CompareFn Fn) {
using BoolT = PrimConv<PT_Bool>::T;
diff --git a/clang/lib/AST/Interp/Opcodes.td b/clang/lib/AST/Interp/Opcodes.td
index ed0774a78833..717c4629fcc3 100644
--- a/clang/lib/AST/Interp/Opcodes.td
+++ b/clang/lib/AST/Interp/Opcodes.td
@@ -94,7 +94,7 @@ def AllTypeClass : TypeClass {
}
def ComparableTypeClass : TypeClass {
- let Types = !listconcat(AluTypeClass.Types, [Ptr], [Float]);
+ let Types = !listconcat(AluTypeClass.Types, [Ptr], [Float], [FnPtr]);
}
class SingletonTypeClass<Type Ty> : TypeClass {
diff --git a/clang/test/AST/Interp/functions.cpp b/clang/test/AST/Interp/functions.cpp
index a8681aae0d58..5bb48ffc54dd 100644
--- a/clang/test/AST/Interp/functions.cpp
+++ b/clang/test/AST/Interp/functions.cpp
@@ -178,6 +178,31 @@ namespace FunctionReturnType {
static_assert(s.fp == nullptr, ""); // zero-initialized function pointer.
}
+namespace Comparison {
+ void f(), g();
+ constexpr void (*pf)() = &f, (*pg)() = &g;
+
+ constexpr bool u13 = pf < pg; // ref-warning {{ordered comparison of function pointers}} \
+ // ref-error {{must be initialized by a constant expression}} \
+ // ref-note {{comparison between '&f' and '&g' has unspecified value}} \
+ // expected-warning {{ordered comparison of function pointers}} \
+ // expected-error {{must be initialized by a constant expression}} \
+ // expected-note {{comparison between '&f' and '&g' has unspecified value}}
+
+ constexpr bool u14 = pf < (void(*)())nullptr; // ref-warning {{ordered comparison of function pointers}} \
+ // ref-error {{must be initialized by a constant expression}} \
+ // ref-note {{comparison between '&f' and 'nullptr' has unspecified value}} \
+ // expected-warning {{ordered comparison of function pointers}} \
+ // expected-error {{must be initialized by a constant expression}} \
+ // expected-note {{comparison between '&f' and 'nullptr' has unspecified value}}
+
+
+
+ static_assert(pf != pg, "");
+ static_assert(pf == &f, "");
+ static_assert(pg == &g, "");
+}
+
}
struct F {
More information about the cfe-commits
mailing list