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?= <tbae...@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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits