[clang] [clang][bytecode] Diagnose non-block pointers in __builtin_is_within_… (PR #228337)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Thu Oct 1 23:02:36 PDT 2026
https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/228337
…lifetime
>From 5ebba93b6d4f3b861560803da03320bb582d28ec Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Fri, 2 Oct 2026 07:59:54 +0200
Subject: [PATCH] [clang][bytecode] Diagnose non-block pointers in
__builtin_is_within_lifetime
---
clang/lib/AST/ByteCode/Interp.cpp | 86 +++++++++----------
clang/lib/AST/ByteCode/InterpBuiltin.cpp | 8 ++
clang/lib/AST/ByteCode/InterpHelpers.h | 1 +
clang/test/AST/ByteCode/builtin-functions.cpp | 6 ++
4 files changed, 56 insertions(+), 45 deletions(-)
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index 25605ba04c7bd..4a8b4e6942f93 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -95,34 +95,6 @@ static void diagnoseMissingInitializer(InterpState &S, CodePtr OpPC,
S.Note(VD->getLocation(), diag::note_declared_at) << VD->getSourceRange();
}
-static void noteValueLocation(InterpState &S, const Block *B) {
- const Descriptor *Desc = B->getDescriptor();
-
- if (B->isDynamic())
- S.Note(Desc->getLocation(), diag::note_constexpr_dynamic_alloc_here);
- else if (B->isTemporary())
- S.Note(Desc->getLocation(), diag::note_constexpr_temporary_here);
- else
- S.Note(Desc->getLocation(), diag::note_declared_at);
-}
-
-static void noteValueLocation(InterpState &S, const Pointer &Ptr) {
- if (Ptr.isBlockPointer()) {
- const Block *B = Ptr.block();
- const Descriptor *Desc = B->getDescriptor();
- if (B->isDynamic())
- S.Note(Desc->getLocation(), diag::note_constexpr_dynamic_alloc_here);
- else if (B->isTemporary())
- S.Note(Desc->getLocation(), diag::note_constexpr_temporary_here);
- else
- S.Note(Desc->getLocation(), diag::note_declared_at);
- return;
- }
-
- if (Ptr.isOpaquePointer())
- S.Note(Ptr.asOpaquePointer().Base.getLocation(), diag::note_declared_at);
-}
-
static void diagnoseNonConstVariable(InterpState &S, CodePtr OpPC,
const ValueDecl *VD,
AccessKinds AK = AK_Read);
@@ -225,6 +197,47 @@ static void diagnoseNonConstVariable(InterpState &S, CodePtr OpPC,
S.Note(VD->getLocation(), diag::note_declared_at);
}
+static bool CheckGlobal(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
+ if (auto ID = Ptr.getDeclID()) {
+ if (!Ptr.isStatic())
+ return true;
+
+ if (S.P.getCurrentDecl() == ID)
+ return true;
+
+ S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_modify_global);
+ return false;
+ }
+ return true;
+}
+
+namespace clang {
+namespace interp {
+
+static void noteValueLocation(InterpState &S, const Block *B) {
+ const Descriptor *Desc = B->getDescriptor();
+
+ if (B->isDynamic())
+ S.Note(Desc->getLocation(), diag::note_constexpr_dynamic_alloc_here);
+ else if (B->isTemporary())
+ S.Note(Desc->getLocation(), diag::note_constexpr_temporary_here);
+ else
+ S.Note(Desc->getLocation(), diag::note_declared_at);
+}
+void noteValueLocation(InterpState &S, const Pointer &Ptr) {
+ if (Ptr.isBlockPointer()) {
+ noteValueLocation(S, Ptr.block());
+ return;
+ }
+
+ if (Ptr.isOpaquePointer())
+ S.Note(Ptr.asOpaquePointer().Base.getLocation(), diag::note_declared_at);
+
+ if (Ptr.isStringPointer())
+ S.Note(Ptr.asStringPointer().getLiteral(),
+ diag::note_constexpr_temporary_here);
+}
+
static bool CheckTemporary(InterpState &S, CodePtr OpPC, const Block *B,
AccessKinds AK) {
if (B->getDeclID()) {
@@ -251,7 +264,6 @@ static bool CheckTemporary(InterpState &S, CodePtr OpPC, const Block *B,
return true;
}
-
static bool CheckTemporary(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
AccessKinds AK) {
if (!Ptr.isBlockPointer())
@@ -259,22 +271,6 @@ static bool CheckTemporary(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
return CheckTemporary(S, OpPC, Ptr.block(), AK);
}
-static bool CheckGlobal(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
- if (auto ID = Ptr.getDeclID()) {
- if (!Ptr.isStatic())
- return true;
-
- if (S.P.getCurrentDecl() == ID)
- return true;
-
- S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_modify_global);
- return false;
- }
- return true;
-}
-
-namespace clang {
-namespace interp {
PRESERVE_NONE static bool BCP(InterpState &S, CodePtr OpPC, int32_t Offset,
PrimType PT);
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index 3303a56f2c053..96c9608b2f79a 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -2446,6 +2446,14 @@ static bool interp__builtin_is_within_lifetime(InterpState &S, CodePtr OpPC,
return false;
}
+ if (!Ptr.isBlockPointer()) {
+ S.FFDiag(S.Current->getSource(OpPC),
+ diag::note_constexpr_access_unreadable_object)
+ << AK_Read << Ptr.toDiagnosticString(S.getASTContext());
+ noteValueLocation(S, Ptr);
+ return false;
+ }
+
// Check if we're currently running an initializer.
if (S.initializingBlock(Ptr.block()))
return Error(2);
diff --git a/clang/lib/AST/ByteCode/InterpHelpers.h b/clang/lib/AST/ByteCode/InterpHelpers.h
index a6c6afeacecb3..0d915566aff4f 100644
--- a/clang/lib/AST/ByteCode/InterpHelpers.h
+++ b/clang/lib/AST/ByteCode/InterpHelpers.h
@@ -47,6 +47,7 @@ bool diagnoseDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
bool arrayElemPtrOpaque(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
APSInt &&Index, bool AllowReplace = true);
+void noteValueLocation(InterpState &S, const Pointer &Ptr);
/// Checks if a pointer is in range.
inline bool CheckRange(InterpState &S, CodePtr OpPC, PtrView Ptr,
diff --git a/clang/test/AST/ByteCode/builtin-functions.cpp b/clang/test/AST/ByteCode/builtin-functions.cpp
index 211c3e98d161c..a1bfab8d54c5b 100644
--- a/clang/test/AST/ByteCode/builtin-functions.cpp
+++ b/clang/test/AST/ByteCode/builtin-functions.cpp
@@ -2044,6 +2044,12 @@ namespace WithinLifetime {
static_assert(__builtin_is_within_lifetime(&temp)); // both-error {{not an integral constant expression}} \
// both-note {{initializer of 'temp' is not a constant expression}}
}
+
+
+ static_assert(__builtin_is_within_lifetime("")); // both-error {{not an integral constant expression}} \
+ // both-note {{whose value is not known}} \
+ // both-note {{temporary created here}}
+
}
#ifdef __SIZEOF_INT128__
More information about the cfe-commits
mailing list