[clang] [clang][bytecode] Start implementing builtin_is_within_lifetime (PR #137765)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 29 00:29:45 PDT 2025
https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/137765
None
>From 609b14ff51520373247a85dc27e11ccc7335cee9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Tue, 29 Apr 2025 09:28:39 +0200
Subject: [PATCH] [clang][bytecode] Start implementing
builtin_is_within_lifetime
---
clang/lib/AST/ByteCode/InterpBuiltin.cpp | 49 +++++++++++++++++++
clang/test/AST/ByteCode/builtin-functions.cpp | 33 +++++++++++++
2 files changed, 82 insertions(+)
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index 34baae1986c35..2804985cb867b 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -2184,6 +2184,50 @@ static bool interp__builtin_object_size(InterpState &S, CodePtr OpPC,
return true;
}
+static bool interp__builtin_is_within_lifetime(InterpState &S, CodePtr OpPC,
+ const CallExpr *Call) {
+
+ if (!S.inConstantContext())
+ return false;
+
+ const Pointer &Ptr = S.Stk.peek<Pointer>();
+
+ auto Error = [&](int Diag) {
+ bool CalledFromStd = false;
+ const auto *Callee = S.Current->getCallee();
+ if (Callee && Callee->isInStdNamespace()) {
+ const IdentifierInfo *Identifier = Callee->getIdentifier();
+ CalledFromStd = Identifier && Identifier->isStr("is_within_lifetime");
+ }
+ S.CCEDiag(CalledFromStd
+ ? S.Current->Caller->getSource(S.Current->getRetPC())
+ : S.Current->getSource(OpPC),
+ diag::err_invalid_is_within_lifetime)
+ << (CalledFromStd ? "std::is_within_lifetime"
+ : "__builtin_is_within_lifetime")
+ << Diag;
+ return false;
+ };
+
+ if (Ptr.isZero())
+ return Error(0);
+ if (Ptr.isOnePastEnd())
+ return Error(1);
+
+ bool Result = true;
+ if (!Ptr.isActive()) {
+ Result = false;
+ } else {
+ if (!CheckLive(S, OpPC, Ptr, AK_Read))
+ return false;
+ if (!CheckMutable(S, OpPC, Ptr))
+ return false;
+ }
+
+ pushInteger(S, Result, Call->getType());
+ return true;
+}
+
bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
uint32_t BuiltinID) {
if (!S.getASTContext().BuiltinInfo.isConstantEvaluated(BuiltinID))
@@ -2693,6 +2737,11 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
return false;
break;
+ case Builtin::BI__builtin_is_within_lifetime:
+ if (!interp__builtin_is_within_lifetime(S, OpPC, Call))
+ return false;
+ break;
+
default:
S.FFDiag(S.Current->getLocation(OpPC),
diag::note_invalid_subexpr_in_const_expr)
diff --git a/clang/test/AST/ByteCode/builtin-functions.cpp b/clang/test/AST/ByteCode/builtin-functions.cpp
index a4c8ec4856ecc..a7fbb1c6743d8 100644
--- a/clang/test/AST/ByteCode/builtin-functions.cpp
+++ b/clang/test/AST/ByteCode/builtin-functions.cpp
@@ -1697,3 +1697,36 @@ namespace Invalid {
static_assert(test() == 0); // both-error {{not an integral constant expression}} \
// both-note {{in call to}}
}
+
+#if __cplusplus >= 202002L
+namespace WithinLifetime {
+ constexpr int a = 10;
+ static_assert(__builtin_is_within_lifetime(&a));
+
+ consteval int IsActive(bool ReadB) {
+ union {
+ int a, b;
+ } A;
+ A.a = 10;
+ if (ReadB)
+ return __builtin_is_within_lifetime(&A.b);
+ return __builtin_is_within_lifetime(&A.a);
+ }
+ static_assert(IsActive(false));
+ static_assert(!IsActive(true));
+
+ static_assert(__builtin_is_within_lifetime((void*)nullptr)); // both-error {{not an integral constant expression}} \
+ // both-note {{'__builtin_is_within_lifetime' cannot be called with a null pointer}}
+
+ constexpr int i = 2;
+ constexpr int arr[2]{};
+ void f() {
+ __builtin_is_within_lifetime(&i + 1); // both-error {{call to consteval function '__builtin_is_within_lifetime' is not a constant expression}} \
+ // both-note {{'__builtin_is_within_lifetime' cannot be called with a one-past-the-end pointer}} \
+ // both-warning {{expression result unused}}
+ __builtin_is_within_lifetime(arr + 2); // both-error {{call to consteval function '__builtin_is_within_lifetime' is not a constant expression}} \
+ // both-note {{'__builtin_is_within_lifetime' cannot be called with a one-past-the-end pointer}} \
+ // both-warning {{expression result unused}}
+ }
+}
+#endif
More information about the cfe-commits
mailing list