[clang] 4bf356b - [clang][bytecode] Start implementing builtin_is_within_lifetime (#137765)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 29 01:57:33 PDT 2025
Author: Timm Baeder
Date: 2025-04-29T10:57:30+02:00
New Revision: 4bf356bbd25ef5950de92b9e66cc8a2d3af583d9
URL: https://github.com/llvm/llvm-project/commit/4bf356bbd25ef5950de92b9e66cc8a2d3af583d9
DIFF: https://github.com/llvm/llvm-project/commit/4bf356bbd25ef5950de92b9e66cc8a2d3af583d9.diff
LOG: [clang][bytecode] Start implementing builtin_is_within_lifetime (#137765)
Added:
Modified:
clang/lib/AST/ByteCode/InterpBuiltin.cpp
clang/test/AST/ByteCode/builtin-functions.cpp
Removed:
################################################################################
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index b6e5b5ffd16ad..8edc6248dcbfd 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -2198,6 +2198,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))
@@ -2707,6 +2751,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 46f9e488db56c..21dca15a45775 100644
--- a/clang/test/AST/ByteCode/builtin-functions.cpp
+++ b/clang/test/AST/ByteCode/builtin-functions.cpp
@@ -1709,3 +1709,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