[clang] [clang][Interp] Implement __builtin_addressof (PR #77303)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Wed Jan 10 09:24:49 PST 2024
Timm =?utf-8?q?Bäder?= <tbaeder at redhat.com>
Message-ID:
In-Reply-To: <llvm.org/llvm/llvm-project/pull/77303 at github.com>
https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/77303
>From aa7ebd9f13d8b7a58f87dc8b00b99acca7f69196 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Mon, 11 Dec 2023 15:12:37 +0100
Subject: [PATCH 1/2] [clang][Interp] Implement __builtin_addressof
We don't need to do anything here, since the input is already a Pointer.
The only complexity is that we pre-classify the parameters as PT_Ptr,
but they might end up being of a different pointer type, e.g. PT_FnPtr.
---
clang/lib/AST/Interp/Interp.cpp | 12 ++++++++++
clang/lib/AST/Interp/InterpBuiltin.cpp | 33 +++++++++++++++++++++++---
clang/test/AST/Interp/functions.cpp | 24 +++++++++++++++++++
3 files changed, 66 insertions(+), 3 deletions(-)
diff --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp
index 21ea2503b94bff..9de0926b9dba9c 100644
--- a/clang/lib/AST/Interp/Interp.cpp
+++ b/clang/lib/AST/Interp/Interp.cpp
@@ -134,6 +134,18 @@ void cleanupAfterFunctionCall(InterpState &S, CodePtr OpPC) {
if (CurFunc->isUnevaluatedBuiltin())
return;
+ // Some builtin functions require us to only look at the call site, since
+ // the classified parameter types do not match.
+ if (CurFunc->isBuiltin()) {
+ const auto *CE =
+ cast<CallExpr>(S.Current->Caller->getExpr(S.Current->getRetPC()));
+ for (int32_t I = CE->getNumArgs() - 1; I >= 0; --I) {
+ const Expr *A = CE->getArg(I);
+ popArg(S, A);
+ }
+ return;
+ }
+
if (S.Current->Caller && CurFunc->isVariadic()) {
// CallExpr we're look for is at the return PC of the current function, i.e.
// in the caller.
diff --git a/clang/lib/AST/Interp/InterpBuiltin.cpp b/clang/lib/AST/Interp/InterpBuiltin.cpp
index b55b1569a25983..d8df81961cc813 100644
--- a/clang/lib/AST/Interp/InterpBuiltin.cpp
+++ b/clang/lib/AST/Interp/InterpBuiltin.cpp
@@ -164,6 +164,8 @@ static bool retPrimValue(InterpState &S, CodePtr OpPC, APValue &Result,
case X: \
return Ret<X>(S, OpPC, Result);
switch (*T) {
+ RET_CASE(PT_Ptr);
+ RET_CASE(PT_FnPtr);
RET_CASE(PT_Float);
RET_CASE(PT_Bool);
RET_CASE(PT_Sint8);
@@ -613,15 +615,34 @@ static bool interp__builtin_ffs(InterpState &S, CodePtr OpPC,
return true;
}
+static bool interp__builtin_addressof(InterpState &S, CodePtr OpPC,
+ const InterpFrame *Frame,
+ const Function *Func,
+ const CallExpr *Call) {
+ PrimType PtrT =
+ S.getContext().classify(Call->getArg(0)->getType()).value_or(PT_Ptr);
+
+ if (PtrT == PT_FnPtr) {
+ const FunctionPointer &Arg = S.Stk.peek<FunctionPointer>();
+ S.Stk.push<FunctionPointer>(Arg);
+ } else if (PtrT == PT_Ptr) {
+ const Pointer &Arg = S.Stk.peek<Pointer>();
+ S.Stk.push<Pointer>(Arg);
+ } else {
+ assert(false);
+ }
+ return true;
+}
+
bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
const CallExpr *Call) {
InterpFrame *Frame = S.Current;
APValue Dummy;
- QualType ReturnType = Call->getCallReturnType(S.getCtx());
- std::optional<PrimType> ReturnT = S.getContext().classify(ReturnType);
+ std::optional<PrimType> ReturnT = S.getContext().classify(Call->getType());
+
// If classify failed, we assume void.
- assert(ReturnT || ReturnType->isVoidType());
+ assert(ReturnT || Call->getType()->isVoidType());
switch (F->getBuiltinID()) {
case Builtin::BI__builtin_is_constant_evaluated:
@@ -820,6 +841,12 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
if (!interp__builtin_ffs(S, OpPC, Frame, F, Call))
return false;
break;
+ case Builtin::BIaddressof:
+ case Builtin::BI__addressof:
+ case Builtin::BI__builtin_addressof:
+ if (!interp__builtin_addressof(S, OpPC, Frame, F, Call))
+ return false;
+ break;
default:
return false;
diff --git a/clang/test/AST/Interp/functions.cpp b/clang/test/AST/Interp/functions.cpp
index 179a195098b132..75f3c5d192b2cf 100644
--- a/clang/test/AST/Interp/functions.cpp
+++ b/clang/test/AST/Interp/functions.cpp
@@ -389,3 +389,27 @@ namespace Packs {
static_assert(foo<int, char>() == 2, "");
static_assert(foo<>() == 0, "");
}
+
+namespace AddressOf {
+ struct S {} s;
+ static_assert(__builtin_addressof(s) == &s, "");
+
+ struct T { constexpr T *operator&() const { return nullptr; } int n; } t;
+ constexpr T *pt = __builtin_addressof(t);
+ static_assert(&pt->n == &t.n, "");
+
+ struct U { int n : 5; } u;
+ int *pbf = __builtin_addressof(u.n); // expected-error {{address of bit-field requested}} \
+ // ref-error {{address of bit-field requested}}
+
+ S *ptmp = __builtin_addressof(S{}); // expected-error {{taking the address of a temporary}} \
+ // expected-warning {{temporary whose address is used as value of local variable 'ptmp' will be destroyed at the end of the full-expression}} \
+ // ref-error {{taking the address of a temporary}} \
+ // ref-warning {{temporary whose address is used as value of local variable 'ptmp' will be destroyed at the end of the full-expression}}
+
+ constexpr int foo() {return 1;}
+ static_assert(__builtin_addressof(foo) == foo, "");
+
+ constexpr _Complex float F = {3, 4};
+ static_assert(__builtin_addressof(F) == &F, "");
+}
>From 313d12467e0c130409f8fd843c140c4817149346 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Wed, 10 Jan 2024 18:24:30 +0100
Subject: [PATCH 2/2] add assertion message
---
clang/lib/AST/Interp/InterpBuiltin.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/AST/Interp/InterpBuiltin.cpp b/clang/lib/AST/Interp/InterpBuiltin.cpp
index d8df81961cc813..754ca96b0c645e 100644
--- a/clang/lib/AST/Interp/InterpBuiltin.cpp
+++ b/clang/lib/AST/Interp/InterpBuiltin.cpp
@@ -629,7 +629,7 @@ static bool interp__builtin_addressof(InterpState &S, CodePtr OpPC,
const Pointer &Arg = S.Stk.peek<Pointer>();
S.Stk.push<Pointer>(Arg);
} else {
- assert(false);
+ assert(false && "Unsupported pointer type passed to __builtin_addressof()");
}
return true;
}
More information about the cfe-commits
mailing list