[clang] a62cd2c - [analyzer][NFC] Take BugReport descriptions as Twine instead of StringRef (#205527)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Jun 24 04:42:46 PDT 2026
Author: Balázs Benics
Date: 2026-06-24T11:42:42Z
New Revision: a62cd2c465310718736956f24cd4d0d5f6cb27b7
URL: https://github.com/llvm/llvm-project/commit/a62cd2c465310718736956f24cd4d0d5f6cb27b7
DIFF: https://github.com/llvm/llvm-project/commit/a62cd2c465310718736956f24cd4d0d5f6cb27b7.diff
LOG: [analyzer][NFC] Take BugReport descriptions as Twine instead of StringRef (#205527)
The constructors of `BugReport`, `BasicBugReport`, and
`PathSensitiveBugReport` previously took the description (and short
description) as `StringRef`. The base class always copies into a
`std::string` member regardless, so taking `const llvm::Twine &` is
strictly more flexible at no storage cost: callers can keep passing
string literals, `StringRef`, `std::string`, `SmallString::str()`, or
`formatv(...).str()` exactly as before, and now they can also pass a
`Twine` concatenation directly without first materializing a temporary
through `SmallString` + `raw_svector_ostream` or `+`/`formatv`.
Assisted-By: claude
Added:
Modified:
clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
clang/lib/StaticAnalyzer/Checkers/CXXDeleteChecker.cpp
clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
clang/lib/StaticAnalyzer/Checkers/UndefinedNewArraySizeChecker.cpp
clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
clang/lib/StaticAnalyzer/Core/BugReporter.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
index 6d2de7a27608c..51c54151ac07b 100644
--- a/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
+++ b/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
@@ -33,6 +33,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/ADT/ilist.h"
#include "llvm/ADT/ilist_node.h"
#include "llvm/ADT/iterator_range.h"
@@ -132,13 +133,13 @@ class BugReport {
SmallVector<std::shared_ptr<PathDiagnosticNotePiece>, 4> Notes;
SmallVector<FixItHint, 4> Fixits;
- BugReport(Kind kind, const BugType &bt, StringRef desc)
+ BugReport(Kind kind, const BugType &bt, const llvm::Twine &desc)
: BugReport(kind, bt, "", desc) {}
- BugReport(Kind K, const BugType &BT, StringRef ShortDescription,
- StringRef Description)
- : K(K), BT(BT), ShortDescription(ShortDescription),
- Description(Description) {}
+ BugReport(Kind K, const BugType &BT, const llvm::Twine &ShortDescription,
+ const llvm::Twine &Description)
+ : K(K), BT(BT), ShortDescription(ShortDescription.str()),
+ Description(Description.str()) {}
public:
virtual ~BugReport() = default;
@@ -252,11 +253,12 @@ class BasicBugReport : public BugReport {
const Decl *DeclWithIssue = nullptr;
public:
- BasicBugReport(const BugType &bt, StringRef desc, PathDiagnosticLocation l)
+ BasicBugReport(const BugType &bt, const llvm::Twine &desc,
+ PathDiagnosticLocation l)
: BugReport(Kind::Basic, bt, desc), Location(l) {}
- BasicBugReport(const BugType &BT, StringRef ShortDesc, StringRef Desc,
- PathDiagnosticLocation L)
+ BasicBugReport(const BugType &BT, const llvm::Twine &ShortDesc,
+ const llvm::Twine &Desc, PathDiagnosticLocation L)
: BugReport(Kind::Basic, BT, ShortDesc, Desc), Location(L) {}
static bool classof(const BugReport *R) {
@@ -369,12 +371,12 @@ class PathSensitiveBugReport : public BugReport {
StackHints;
public:
- PathSensitiveBugReport(const BugType &bt, StringRef desc,
+ PathSensitiveBugReport(const BugType &bt, const llvm::Twine &desc,
const ExplodedNode *errorNode)
: PathSensitiveBugReport(bt, desc, desc, errorNode) {}
- PathSensitiveBugReport(const BugType &bt, StringRef shortDesc, StringRef desc,
- const ExplodedNode *errorNode)
+ PathSensitiveBugReport(const BugType &bt, const llvm::Twine &shortDesc,
+ const llvm::Twine &desc, const ExplodedNode *errorNode)
: PathSensitiveBugReport(bt, shortDesc, desc, errorNode,
/*LocationToUnique*/ {},
/*DeclToUnique*/ nullptr) {}
@@ -386,15 +388,15 @@ class PathSensitiveBugReport : public BugReport {
/// to the user. This method allows to rest the location which should be used
/// for uniquing reports. For example, memory leaks checker, could set this to
/// the allocation site, rather then the location where the bug is reported.
- PathSensitiveBugReport(const BugType &bt, StringRef desc,
+ PathSensitiveBugReport(const BugType &bt, const llvm::Twine &desc,
const ExplodedNode *errorNode,
PathDiagnosticLocation LocationToUnique,
const Decl *DeclToUnique)
: PathSensitiveBugReport(bt, desc, desc, errorNode, LocationToUnique,
DeclToUnique) {}
- PathSensitiveBugReport(const BugType &bt, StringRef shortDesc, StringRef desc,
- const ExplodedNode *errorNode,
+ PathSensitiveBugReport(const BugType &bt, const llvm::Twine &shortDesc,
+ const llvm::Twine &desc, const ExplodedNode *errorNode,
PathDiagnosticLocation LocationToUnique,
const Decl *DeclToUnique);
diff --git a/clang/lib/StaticAnalyzer/Checkers/CXXDeleteChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CXXDeleteChecker.cpp
index bfab91dd67919..0bc628eaabe8c 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CXXDeleteChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CXXDeleteChecker.cpp
@@ -156,19 +156,17 @@ void CXXArrayDeleteChecker::checkTypedDeleteExpr(
if (!N)
return;
- SmallString<256> Buf;
- llvm::raw_svector_ostream OS(Buf);
-
QualType SourceType = BaseClassRegion->getValueType();
QualType TargetType =
DerivedClassRegion->getSymbol()->getType()->getPointeeType();
- OS << "Deleting an array of '" << TargetType.getAsString()
- << "' objects as their base class '"
- << SourceType.getAsString(C.getASTContext().getPrintingPolicy())
- << "' is undefined";
-
- auto R = std::make_unique<PathSensitiveBugReport>(BT, OS.str(), N);
+ auto R = std::make_unique<PathSensitiveBugReport>(
+ BT,
+ "Deleting an array of '" + Twine(TargetType.getAsString()) +
+ "' objects as their base class '" +
+ SourceType.getAsString(C.getASTContext().getPrintingPolicy()) +
+ "' is undefined",
+ N);
// Mark region of problematic base class for later use in the BugVisitor.
R->markInteresting(BaseClassRegion);
diff --git a/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
index 5d4a8b6b24766..02794da032f2f 100644
--- a/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
@@ -19,8 +19,6 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/Support/raw_ostream.h"
#include <optional>
using namespace clang;
@@ -226,14 +224,14 @@ void MacOSKeychainAPIChecker::
if (!N)
return;
- SmallString<80> sbuf;
- llvm::raw_svector_ostream os(sbuf);
unsigned int PDeallocIdx =
- FunctionsToTrack[AP.second->AllocatorIdx].DeallocatorIdx;
+ FunctionsToTrack[AP.second->AllocatorIdx].DeallocatorIdx;
- os << "Deallocator doesn't match the allocator: '"
- << FunctionsToTrack[PDeallocIdx].Name << "' should be used.";
- auto Report = std::make_unique<PathSensitiveBugReport>(BT, os.str(), N);
+ auto Report = std::make_unique<PathSensitiveBugReport>(
+ BT,
+ "Deallocator doesn't match the allocator: '" +
+ Twine(FunctionsToTrack[PDeallocIdx].Name) + "' should be used.",
+ N);
Report->addVisitor(std::make_unique<SecKeychainBugVisitor>(AP.first));
Report->addRange(ArgExpr->getSourceRange());
markInteresting(Report.get(), AP);
@@ -269,14 +267,13 @@ void MacOSKeychainAPIChecker::checkPreStmt(const CallExpr *CE,
ExplodedNode *N = C.generateNonFatalErrorNode(State);
if (!N)
return;
- SmallString<128> sbuf;
- llvm::raw_svector_ostream os(sbuf);
unsigned int DIdx = FunctionsToTrack[AS->AllocatorIdx].DeallocatorIdx;
- os << "Allocated data should be released before another call to "
- << "the allocator: missing a call to '"
- << FunctionsToTrack[DIdx].Name
- << "'.";
- auto Report = std::make_unique<PathSensitiveBugReport>(BT, os.str(), N);
+ auto Report = std::make_unique<PathSensitiveBugReport>(
+ BT,
+ "Allocated data should be released before another call to "
+ "the allocator: missing a call to '" +
+ Twine(FunctionsToTrack[DIdx].Name) + "'.",
+ N);
Report->addVisitor(std::make_unique<SecKeychainBugVisitor>(V));
Report->addRange(ArgExpr->getSourceRange());
Report->markInteresting(AS->Region);
@@ -463,10 +460,6 @@ std::unique_ptr<PathSensitiveBugReport>
MacOSKeychainAPIChecker::generateAllocatedDataNotReleasedReport(
const AllocationPair &AP, ExplodedNode *N, CheckerContext &C) const {
const ADFunctionInfo &FI = FunctionsToTrack[AP.second->AllocatorIdx];
- SmallString<70> sbuf;
- llvm::raw_svector_ostream os(sbuf);
- os << "Allocated data is not released: missing a call to '"
- << FunctionsToTrack[FI.DeallocatorIdx].Name << "'.";
// Most bug reports are cached at the location where they occurred.
// With leaks, we want to unique them by the location where they were
@@ -480,8 +473,10 @@ MacOSKeychainAPIChecker::generateAllocatedDataNotReleasedReport(
AllocStmt, C.getSourceManager(), AllocNode->getStackFrame());
auto Report = std::make_unique<PathSensitiveBugReport>(
- BT, os.str(), N, LocUsedForUniqueing,
- AllocNode->getStackFrame()->getDecl());
+ BT,
+ "Allocated data is not released: missing a call to '" +
+ Twine(FunctionsToTrack[FI.DeallocatorIdx].Name) + "'.",
+ N, LocUsedForUniqueing, AllocNode->getStackFrame()->getDecl());
Report->addVisitor(std::make_unique<SecKeychainBugVisitor>(AP.first));
markInteresting(Report.get(), AP);
diff --git a/clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
index 4b55c7c49caa8..2cc633fa5649f 100644
--- a/clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
@@ -22,7 +22,6 @@
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
-#include "llvm/ADT/StringExtras.h"
using namespace clang;
using namespace ento;
@@ -280,14 +279,11 @@ std::unique_ptr<PathSensitiveBugReport>
NonNullParamChecker::genReportNullAttrNonNull(const ExplodedNode *ErrorNode,
const Expr *ArgE,
unsigned IdxOfArg) const {
- llvm::SmallString<256> SBuf;
- llvm::raw_svector_ostream OS(SBuf);
- OS << "Null pointer passed to "
- << IdxOfArg << llvm::getOrdinalSuffix(IdxOfArg)
- << " parameter expecting 'nonnull'";
-
- auto R =
- std::make_unique<PathSensitiveBugReport>(BTAttrNonNull, SBuf, ErrorNode);
+ auto R = std::make_unique<PathSensitiveBugReport>(
+ BTAttrNonNull,
+ "Null pointer passed to " + Twine(IdxOfArg) +
+ llvm::getOrdinalSuffix(IdxOfArg) + " parameter expecting 'nonnull'",
+ ErrorNode);
if (ArgE)
bugreporter::trackExpressionValue(ErrorNode, ArgE, *R);
diff --git a/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
index 2839ef0b6d2e6..5de7daae1b10f 100644
--- a/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
@@ -10,15 +10,13 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/Attr.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/Support/raw_ostream.h"
#include <optional>
using namespace clang;
@@ -70,14 +68,11 @@ UndefCapturedBlockVarChecker::checkPostStmt(const BlockExpr *BE,
if (std::optional<UndefinedVal> V =
state->getSVal(Var.getOriginalRegion()).getAs<UndefinedVal>()) {
if (ExplodedNode *N = C.generateErrorNode()) {
- // Generate a bug report.
- SmallString<128> buf;
- llvm::raw_svector_ostream os(buf);
-
- os << "Variable '" << VD->getName()
- << "' is uninitialized when captured by block";
-
- auto R = std::make_unique<PathSensitiveBugReport>(BT, os.str(), N);
+ auto R = std::make_unique<PathSensitiveBugReport>(
+ BT,
+ "Variable '" + Twine(VD->getName()) +
+ "' is uninitialized when captured by block",
+ N);
if (const Expr *Ex = FindBlockDeclRefExpr(BE->getBody(), VD))
R->addRange(Ex->getSourceRange());
bugreporter::trackStoredValue(*V, VR, *R,
diff --git a/clang/lib/StaticAnalyzer/Checkers/UndefinedNewArraySizeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UndefinedNewArraySizeChecker.cpp
index f053ee887a1aa..dcab55a7e370d 100644
--- a/clang/lib/StaticAnalyzer/Checkers/UndefinedNewArraySizeChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/UndefinedNewArraySizeChecker.cpp
@@ -55,13 +55,8 @@ void UndefinedNewArraySizeChecker::HandleUndefinedArrayElementCount(
CheckerContext &C, SVal ArgVal, const Expr *Init, SourceRange Range) const {
if (ExplodedNode *N = C.generateErrorNode()) {
-
- SmallString<100> buf;
- llvm::raw_svector_ostream os(buf);
-
- os << "Element count in new[] is a garbage value";
-
- auto R = std::make_unique<PathSensitiveBugReport>(BT, os.str(), N);
+ auto R = std::make_unique<PathSensitiveBugReport>(
+ BT, "Element count in new[] is a garbage value", N);
R->markInteresting(ArgVal);
R->addRange(Range);
bugreporter::trackExpressionValue(N, Init, *R);
diff --git a/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
index 4df751d203973..e51a74f725975 100644
--- a/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
@@ -22,8 +22,6 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/Support/raw_ostream.h"
#include <optional>
using namespace clang;
@@ -480,11 +478,9 @@ bool UnixAPIPortabilityChecker::ReportZeroByteAllocation(
if (!N)
return false;
- SmallString<256> S;
- llvm::raw_svector_ostream os(S);
- os << "Call to '" << fn_name << "' has an allocation size of 0 bytes";
- auto report =
- std::make_unique<PathSensitiveBugReport>(BT_mallocZero, os.str(), N);
+ auto report = std::make_unique<PathSensitiveBugReport>(
+ BT_mallocZero,
+ "Call to '" + Twine(fn_name) + "' has an allocation size of 0 bytes", N);
report->addRange(arg->getSourceRange());
bugreporter::trackExpressionValue(N, arg, *report);
diff --git a/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
index d5c91a20d60b2..1d82ac0f7225a 100644
--- a/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
@@ -21,7 +21,6 @@
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h"
-#include "llvm/Support/raw_ostream.h"
#include <optional>
using namespace clang;
@@ -213,12 +212,11 @@ void VLASizeChecker::reportTaintBug(const Expr *SizeE, ProgramStateRef State,
if (!N)
return;
- SmallString<256> buf;
- llvm::raw_svector_ostream os(buf);
- os << "Declared variable-length array (VLA) ";
- os << "has tainted (attacker controlled) size that can be 0 or negative";
-
- auto report = std::make_unique<PathSensitiveBugReport>(TaintBT, os.str(), N);
+ auto report = std::make_unique<PathSensitiveBugReport>(
+ TaintBT,
+ "Declared variable-length array (VLA) has tainted (attacker controlled) "
+ "size that can be 0 or negative",
+ N);
report->addRange(SizeE->getSourceRange());
bugreporter::trackExpressionValue(N, SizeE, *report);
// The vla size may be a complex expression where multiple memory locations
diff --git a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
index b6c709963501f..b609a98b0aed2 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -2154,7 +2154,7 @@ LLVM_ATTRIBUTE_USED static bool isHidden(const CheckerRegistryData &Registry,
}
PathSensitiveBugReport::PathSensitiveBugReport(
- const BugType &bt, StringRef shortDesc, StringRef desc,
+ const BugType &bt, const llvm::Twine &shortDesc, const llvm::Twine &desc,
const ExplodedNode *errorNode, PathDiagnosticLocation LocationToUnique,
const Decl *DeclToUnique)
: BugReport(Kind::PathSensitive, bt, shortDesc, desc), ErrorNode(errorNode),
More information about the cfe-commits
mailing list