mirror of
https://github.com/intel/llvm.git
synced 2026-01-24 17:01:00 +08:00
[clang][bytecode] Start implementing builtin_is_within_lifetime (#137765)
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user