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