[llvm-branch-commits] [clang-tools-extra] [clang-tidy] support to detect conversion in `make_optional` for `bugprone-optional-value-conversion` (PR #130417)
Congcong Cai via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Mar 10 23:54:57 PDT 2025
https://github.com/HerrCai0907 updated https://github.com/llvm/llvm-project/pull/130417
>From 1706e3fc5819602febf9dfa554e98eb1e1fea365 Mon Sep 17 00:00:00 2001
From: Congcong Cai <congcongcai0907 at 163.com>
Date: Sat, 8 Mar 2025 21:50:19 +0800
Subject: [PATCH] [clang-tidy] support to detect conversion in `make_optional`
for `bugprone-optional-value-conversion`
Fixes: #119554
---
.../bugprone/OptionalValueConversionCheck.cpp | 14 ++++++++++++++
clang-tools-extra/docs/ReleaseNotes.rst | 4 ++++
...ptional-value-conversion-construct-from-std.cpp | 13 +++++++++++++
3 files changed, 31 insertions(+)
diff --git a/clang-tools-extra/clang-tidy/bugprone/OptionalValueConversionCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/OptionalValueConversionCheck.cpp
index 33e823ac07490..cb5a1c7bea801 100644
--- a/clang-tools-extra/clang-tidy/bugprone/OptionalValueConversionCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/OptionalValueConversionCheck.cpp
@@ -12,6 +12,7 @@
#include "../utils/OptionsUtils.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
#include <array>
using namespace clang::ast_matchers;
@@ -31,6 +32,7 @@ constexpr std::array<StringRef, 2> MakeSmartPtrList{
"::std::make_unique",
"::std::make_shared",
};
+constexpr StringRef MakeOptional = "::std::make_optional";
} // namespace
@@ -86,6 +88,18 @@ void OptionalValueConversionCheck::registerMatchers(MatchFinder *Finder) {
callee(functionDecl(
matchers::matchesAnyListedName(MakeSmartPtrList),
hasTemplateArgument(0, refersToType(BindOptionalType)))),
+ hasArgument(0, OptionalDerefMatcher)),
+ callExpr(
+ // match first std::make_optional by limit argument count (1)
+ // and template count (1).
+ // 1. template< class T > constexpr
+ // std::optional<decay_t<T>> make_optional(T&& value);
+ // 2. template< class T, class... Args > constexpr
+ // std::optional<T> make_optional(Args&&... args);
+ argumentCountIs(1),
+ callee(functionDecl(templateArgumentCountIs(1),
+ hasName(MakeOptional),
+ returns(BindOptionalType))),
hasArgument(0, OptionalDerefMatcher))),
unless(anyOf(hasAncestor(typeLoc()),
hasAncestor(expr(matchers::hasUnevaluatedContext())))))
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index fa68b6fabd549..5e2d87e0c2fa1 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -124,6 +124,10 @@ Changes in existing checks
no longer be needed and will be removed. Also fixing false positive from
const reference accessors to objects containing optional member.
+- Improved :doc:`bugprone-optional-value-conversion
+ <clang-tidy/checks/bugprone/optional-value-conversion>` check to detect
+ conversion in argument of ``std::make_optional``.
+
- Improved :doc:`bugprone-unsafe-functions
<clang-tidy/checks/bugprone/unsafe-functions>` check to allow specifying
additional C++ member functions to match.
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/optional-value-conversion-construct-from-std.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/optional-value-conversion-construct-from-std.cpp
index 768ab1ce014ce..305fd6890710d 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/optional-value-conversion-construct-from-std.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/optional-value-conversion-construct-from-std.cpp
@@ -27,9 +27,19 @@ class unique_ptr {};
template <typename type>
class shared_ptr {};
+template <typename T>
+class initializer_list {};
+
template <class T, class... Args> unique_ptr<T> make_unique(Args &&...args);
template <class T, class... Args> shared_ptr<T> make_shared(Args &&...args);
+template <class T>
+constexpr std::optional<__decay(T)> make_optional(T &&value);
+template <class T, class... Args>
+constexpr std::optional<T> make_optional(Args &&...args);
+template <class T, class U, class... Args>
+constexpr std::optional<T> make_optional(std::initializer_list<U> il, Args &&...args);
+
} // namespace std
struct A {
@@ -45,9 +55,12 @@ void invalid() {
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
std::make_shared<std::optional<int>>(opt.value());
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
+ std::make_optional(opt.value());
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
}
void valid() {
std::make_unique<A>(opt.value());
std::make_shared<A>(opt.value());
+ std::make_optional<int>(opt.value());
}
More information about the llvm-branch-commits
mailing list