[clang-tools-extra] [clang-tidy] Modernize-use-string-view: fix todo for ternary (PR #209008)
Zinovy Nis via cfe-commits
cfe-commits at lists.llvm.org
Sun Jul 12 04:54:58 PDT 2026
https://github.com/irishrover created https://github.com/llvm/llvm-project/pull/209008
Add a support for any-depth ternary expressions
>From dbdb9e318ff3cef64b125ae2afddd3cfaec5f056 Mon Sep 17 00:00:00 2001
From: Zinovy Nis <zinovy.nis at gmail.com>
Date: Sun, 12 Jul 2026 14:52:20 +0300
Subject: [PATCH] [clang-tidy] Modernize-use-string-view: fix todo for ternary
Add a support for any-depth ternary expressions
---
.../modernize/UseStringViewCheck.cpp | 17 ++++++++++++----
.../checkers/modernize/use-string-view.cpp | 20 ++++++++++++++++++-
2 files changed, 32 insertions(+), 5 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/modernize/UseStringViewCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseStringViewCheck.cpp
index 5209846aca567..3464c6ace8305 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseStringViewCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseStringViewCheck.cpp
@@ -22,6 +22,17 @@ using namespace clang::ast_matchers;
namespace clang::tidy::modernize {
namespace {
+AST_MATCHER(Expr, isStringLiteralOrTernary) {
+ const auto Matches = [](const auto &Self, const Expr &Expression) -> bool {
+ const Expr *Unwrapped = Expression.IgnoreParenImpCasts();
+ if (const auto *Ternary = dyn_cast<ConditionalOperator>(Unwrapped))
+ return Self(Self, *Ternary->getTrueExpr()) &&
+ Self(Self, *Ternary->getFalseExpr());
+ return isa<StringLiteral>(Unwrapped);
+ };
+ return Matches(Matches, Node);
+}
+
AST_MATCHER(FunctionDecl, isOverloaded) {
const DeclarationName Name = Node.getDeclName();
// Sanity check
@@ -106,9 +117,6 @@ void UseStringViewCheck::registerMatchers(MatchFinder *Finder) {
const auto IsStdStringView = getStringTypeMatcher("::std::basic_string_view");
const auto IgnoredFunctionsMatcher =
matchers::matchesAnyListedRegexName(IgnoredFunctions);
- const auto TernaryOperator = conditionalOperator(
- hasTrueExpression(ignoringParenImpCasts(stringLiteral())),
- hasFalseExpression(ignoringParenImpCasts(stringLiteral())));
const auto VirtualOrOperator =
cxxMethodDecl(anyOf(cxxConversionDecl(), isVirtual()));
const auto CheckOverloaded =
@@ -121,7 +129,8 @@ void UseStringViewCheck::registerMatchers(MatchFinder *Finder) {
ast_matchers::isExplicitTemplateSpecialization())),
returns(IsStdString), hasDescendant(returnStmt()),
unless(hasDescendant(returnStmt(hasReturnValue(unless(
- anyOf(stringLiteral(), hasType(IsStdStringView), TernaryOperator,
+ anyOf(stringLiteral(), hasType(IsStdStringView),
+ isStringLiteralOrTernary(),
cxxConstructExpr(anyOf(
allOf(hasType(IsStdString), argumentCountIs(0)),
allOf(isListInitialization(),
diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-string-view.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-string-view.cpp
index 26a72c1c242e1..1189d690664d4 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-string-view.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-string-view.cpp
@@ -136,10 +136,21 @@ std::string ternary(bool flag) {
}
std::string nested(int x) {
- // TODO: support for nested ternary
+// CHECK-MESSAGES:[[@LINE-1]]:1: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view]
+// CHECK-FIXES: std::string_view nested(int x) {
return x < 0 ? "neg" : (x == 0 ? "zero" : "pos");
}
+std::string deeplyNested(int x) {
+// CHECK-MESSAGES:[[@LINE-1]]:1: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view]
+// CHECK-FIXES: std::string_view deeplyNested(int x) {
+ return x < 0 ? "negative"
+ : (x == 0 ? "zero"
+ : (x == 1 ? "one"
+ : (x == 2 ? "two"
+ : (x == 3 ? "three" : "many"))));
+}
+
class A {
std::string classMethodInt() { return "internal"; }
// CHECK-MESSAGES:[[@LINE-1]]:3: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view]
@@ -207,6 +218,13 @@ MyString<wchar_t> aliasedWChar() {
// Negative tests
// ==========================================================
+std::string nestedTernaryWithLocalString(int x) {
+ std::string local = "local";
+ // Must not be converted because one branch returns a local string.
+ return x < 0 ? "negative"
+ : (x == 0 ? "zero" : (x == 1 ? local : "positive"));
+}
+
std::string toString() {
return "ignored by default options";
}
More information about the cfe-commits
mailing list