[clang] [clang] Return std::optional from all Expr::tryEvaluate* API (PR #179230)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Mon Feb 2 06:04:24 PST 2026
https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/179230
>From 5fabd2f531a3e5b850d461d1aa066873d82f62d4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Mon, 2 Feb 2026 14:29:05 +0100
Subject: [PATCH] [clang] Return std::optional from all Expr::tryEvaluate* API
tryEvaluateString was returning an std::optional, but the other try* API
was not. Update tryEvaluateObjectSize and tryEvaluateStrLen to return an
std::optional<uint64_t>.
---
clang/include/clang/AST/Expr.h | 6 ++---
clang/lib/AST/ExprConstant.cpp | 35 +++++++++++++++++--------
clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 9 ++++---
clang/lib/CodeGen/CGBuiltin.cpp | 9 ++++---
clang/lib/Sema/SemaChecking.cpp | 24 +++++++++--------
5 files changed, 50 insertions(+), 33 deletions(-)
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 3e30a8b420f19..4bea35015827a 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -774,14 +774,14 @@ class Expr : public ValueStmt {
///
/// \param Type - How to evaluate the size of the Expr, as defined by the
/// "type" parameter of __builtin_object_size
- bool tryEvaluateObjectSize(uint64_t &Result, ASTContext &Ctx,
- unsigned Type) const;
+ std::optional<uint64_t> tryEvaluateObjectSize(const ASTContext &Ctx,
+ unsigned Type) const;
/// If the current Expr is a pointer, this will try to statically
/// determine the strlen of the string pointed to.
/// Returns true if all of the above holds and we were able to figure out the
/// strlen, false otherwise.
- bool tryEvaluateStrLen(uint64_t &Result, ASTContext &Ctx) const;
+ std::optional<uint64_t> tryEvaluateStrLen(const ASTContext &Ctx) const;
bool EvaluateCharRangeAsString(std::string &Result,
const Expr *SizeExpression,
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 8f4907e6db01e..d1f061d610b1a 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -21659,18 +21659,25 @@ bool Expr::isPotentialConstantExprUnevaluated(Expr *E,
return Diags.empty();
}
-bool Expr::tryEvaluateObjectSize(uint64_t &Result, ASTContext &Ctx,
- unsigned Type) const {
+std::optional<uint64_t> Expr::tryEvaluateObjectSize(const ASTContext &Ctx,
+ unsigned Type) const {
if (!getType()->isPointerType())
return false;
Expr::EvalStatus Status;
EvalInfo Info(Ctx, Status, EvaluationMode::ConstantFold);
- if (Info.EnableNewConstInterp) {
- return Info.Ctx.getInterpContext().tryEvaluateObjectSize(Info, this, Type,
- Result);
- }
- return tryEvaluateBuiltinObjectSize(this, Type, Info, Result);
+ uint64_t Result = ~0u;
+ bool Success;
+ if (Info.EnableNewConstInterp)
+ Success = Info.Ctx.getInterpContext().tryEvaluateObjectSize(Info, this,
+ Type, Result);
+ else
+ Success = tryEvaluateBuiltinObjectSize(this, Type, Info, Result);
+
+ if (!Success)
+ return std::nullopt;
+
+ return Result;
}
static bool EvaluateBuiltinStrLen(const Expr *E, uint64_t &Result,
@@ -21814,14 +21821,20 @@ bool Expr::EvaluateCharRangeAsString(APValue &Result,
PtrExpression, Ctx, Status);
}
-bool Expr::tryEvaluateStrLen(uint64_t &Result, ASTContext &Ctx) const {
+std::optional<uint64_t> Expr::tryEvaluateStrLen(const ASTContext &Ctx) const {
Expr::EvalStatus Status;
EvalInfo Info(Ctx, Status, EvaluationMode::ConstantFold);
- if (Info.EnableNewConstInterp)
- return Info.Ctx.getInterpContext().evaluateStrlen(Info, this, Result);
+ uint64_t Result = ~0u;
+ if (Info.EnableNewConstInterp) {
+ if (!Info.Ctx.getInterpContext().evaluateStrlen(Info, this, Result))
+ return std::nullopt;
+ } else {
+ if (!EvaluateBuiltinStrLen(this, Result, Info))
+ return std::nullopt;
+ }
- return EvaluateBuiltinStrLen(this, Result, Info);
+ return Result;
}
namespace {
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index 580ada8901cbb..71c1003a3bffb 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -2033,8 +2033,9 @@ mlir::Value CIRGenFunction::emitBuiltinObjectSize(const Expr *e, unsigned type,
mlir::Value CIRGenFunction::evaluateOrEmitBuiltinObjectSize(
const Expr *e, unsigned type, cir::IntType resType, mlir::Value emittedE,
bool isDynamic) {
- uint64_t objectSize;
- if (!e->tryEvaluateObjectSize(objectSize, getContext(), type))
- return emitBuiltinObjectSize(e, type, resType, emittedE, isDynamic);
- return builder.getConstInt(getLoc(e->getSourceRange()), resType, objectSize);
+ if (std::optional<uint64_t> objectSize =
+ e->tryEvaluateObjectSize(getContext(), type))
+ return builder.getConstInt(getLoc(e->getSourceRange()), resType,
+ *objectSize);
+ return emitBuiltinObjectSize(e, type, resType, emittedE, isDynamic);
}
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 339d6cff0a386..2624096e7ddc0 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -924,10 +924,11 @@ CodeGenFunction::evaluateOrEmitBuiltinObjectSize(const Expr *E, unsigned Type,
llvm::IntegerType *ResType,
llvm::Value *EmittedE,
bool IsDynamic) {
- uint64_t ObjectSize;
- if (!E->tryEvaluateObjectSize(ObjectSize, getContext(), Type))
- return emitBuiltinObjectSize(E, Type, ResType, EmittedE, IsDynamic);
- return ConstantInt::get(ResType, ObjectSize, /*isSigned=*/true);
+
+ if (std::optional<uint64_t> ObjectSize =
+ E->tryEvaluateObjectSize(getContext(), Type))
+ return ConstantInt::get(ResType, *ObjectSize, /*isSigned=*/true);
+ return emitBuiltinObjectSize(E, Type, ResType, EmittedE, IsDynamic);
}
namespace {
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index e2e1b37572364..c0e1f019363f8 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -1217,12 +1217,12 @@ void Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD,
return std::nullopt;
const Expr *ObjArg = TheCall->getArg(NewIndex);
- uint64_t Result;
- if (!ObjArg->tryEvaluateObjectSize(Result, getASTContext(), BOSType))
- return std::nullopt;
-
- // Get the object size in the target's size_t width.
- return llvm::APSInt::getUnsigned(Result).extOrTrunc(SizeTypeWidth);
+ if (std::optional<uint64_t> ObjSize =
+ ObjArg->tryEvaluateObjectSize(getASTContext(), BOSType)) {
+ // Get the object size in the target's size_t width.
+ return llvm::APSInt::getUnsigned(*ObjSize).extOrTrunc(SizeTypeWidth);
+ }
+ return std::nullopt;
};
auto ComputeStrLenArgument =
@@ -1233,11 +1233,13 @@ void Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD,
unsigned NewIndex = *IndexOptional;
const Expr *ObjArg = TheCall->getArg(NewIndex);
- uint64_t Result;
- if (!ObjArg->tryEvaluateStrLen(Result, getASTContext()))
- return std::nullopt;
- // Add 1 for null byte.
- return llvm::APSInt::getUnsigned(Result + 1).extOrTrunc(SizeTypeWidth);
+
+ if (std::optional<uint64_t> Result =
+ ObjArg->tryEvaluateStrLen(getASTContext())) {
+ // Add 1 for null byte.
+ return llvm::APSInt::getUnsigned(*Result + 1).extOrTrunc(SizeTypeWidth);
+ }
+ return std::nullopt;
};
std::optional<llvm::APSInt> SourceSize;
More information about the cfe-commits
mailing list