[clang] [clang][Interp] Fix function pointer callexpr eval order (PR #101821)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Sat Aug 3 06:08:37 PDT 2024
https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/101821
We need to evaluate the callee before the arguments.
>From ef92f7ef23014f001630fe9d30cdf7c39d19bfbf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Sat, 3 Aug 2024 15:06:12 +0200
Subject: [PATCH] [clang][Interp] Fix function pointer callexpr eval order
We need to evaluate the callee before the arguments.
---
clang/lib/AST/Interp/Compiler.cpp | 22 +++++++++++++---------
clang/test/AST/Interp/eval-order.cpp | 5 ++---
2 files changed, 15 insertions(+), 12 deletions(-)
diff --git a/clang/lib/AST/Interp/Compiler.cpp b/clang/lib/AST/Interp/Compiler.cpp
index e1fa0eb1eacb3..ada22b569b2b0 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -4003,6 +4003,13 @@ bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {
} else if (!this->visit(MC->getImplicitObjectArgument())) {
return false;
}
+ } else if (!FuncDecl) {
+ const Expr *Callee = E->getCallee();
+ CalleeOffset = this->allocateLocalPrimitive(Callee, PT_FnPtr, true, false);
+ if (!this->visit(Callee))
+ return false;
+ if (!this->emitSetLocal(PT_FnPtr, *CalleeOffset, E))
+ return false;
}
llvm::BitVector NonNullArgs = collectNonNullArgs(FuncDecl, Args);
@@ -4071,22 +4078,19 @@ bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {
for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)
ArgSize += align(primSize(classify(E->getArg(I)).value_or(PT_Ptr)));
- // Get the callee, either from a member pointer saved in CalleeOffset,
- // or by just visiting the Callee expr.
- if (CalleeOffset) {
+ // Get the callee, either from a member pointer or function pointer saved in
+ // CalleeOffset.
+ if (isa<CXXMemberCallExpr>(E) && CalleeOffset) {
if (!this->emitGetLocal(PT_MemberPtr, *CalleeOffset, E))
return false;
if (!this->emitGetMemberPtrDecl(E))
return false;
- if (!this->emitCallPtr(ArgSize, E, E))
- return false;
} else {
- if (!this->visit(E->getCallee()))
- return false;
-
- if (!this->emitCallPtr(ArgSize, E, E))
+ if (!this->emitGetLocal(PT_FnPtr, *CalleeOffset, E))
return false;
}
+ if (!this->emitCallPtr(ArgSize, E, E))
+ return false;
}
// Cleanup for discarded return values.
diff --git a/clang/test/AST/Interp/eval-order.cpp b/clang/test/AST/Interp/eval-order.cpp
index 77f50831f4f47..d9cfd0b4642fa 100644
--- a/clang/test/AST/Interp/eval-order.cpp
+++ b/clang/test/AST/Interp/eval-order.cpp
@@ -45,7 +45,7 @@ namespace EvalOrder {
}
template <typename T> constexpr T &&b(T &&v) {
if (!done_a)
- throw "wrong"; // expected-note 5{{not valid}}
+ throw "wrong"; // expected-note 4{{not valid}}
done_b = true;
return (T &&)v;
}
@@ -75,8 +75,7 @@ namespace EvalOrder {
SEQ(A(&ud)->*B(&UserDefined::n));
// Rule 4: a(b1, b2, b3)
- SEQ(A(f)(B(1), B(2), B(3))); // expected-error {{not an integral constant expression}} FIXME \
- // expected-note 2{{in call to}}
+ SEQ(A(f)(B(1), B(2), B(3)));
// Rule 5: b = a, b @= a
SEQ(B(lvalue<int>().get()) = A(0)); // expected-error {{not an integral constant expression}} FIXME \
More information about the cfe-commits
mailing list