Skip to content

Commit 1706e3f

Browse files
committed
[clang-tidy] support to detect conversion in make_optional for bugprone-optional-value-conversion
Fixes: #119554
1 parent b28bd17 commit 1706e3f

File tree

3 files changed

+31
-0
lines changed

3 files changed

+31
-0
lines changed

clang-tools-extra/clang-tidy/bugprone/OptionalValueConversionCheck.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "../utils/OptionsUtils.h"
1313
#include "clang/AST/ASTContext.h"
1414
#include "clang/ASTMatchers/ASTMatchFinder.h"
15+
#include "clang/ASTMatchers/ASTMatchers.h"
1516
#include <array>
1617

1718
using namespace clang::ast_matchers;
@@ -31,6 +32,7 @@ constexpr std::array<StringRef, 2> MakeSmartPtrList{
3132
"::std::make_unique",
3233
"::std::make_shared",
3334
};
35+
constexpr StringRef MakeOptional = "::std::make_optional";
3436

3537
} // namespace
3638

@@ -86,6 +88,18 @@ void OptionalValueConversionCheck::registerMatchers(MatchFinder *Finder) {
8688
callee(functionDecl(
8789
matchers::matchesAnyListedName(MakeSmartPtrList),
8890
hasTemplateArgument(0, refersToType(BindOptionalType)))),
91+
hasArgument(0, OptionalDerefMatcher)),
92+
callExpr(
93+
// match first std::make_optional by limit argument count (1)
94+
// and template count (1).
95+
// 1. template< class T > constexpr
96+
// std::optional<decay_t<T>> make_optional(T&& value);
97+
// 2. template< class T, class... Args > constexpr
98+
// std::optional<T> make_optional(Args&&... args);
99+
argumentCountIs(1),
100+
callee(functionDecl(templateArgumentCountIs(1),
101+
hasName(MakeOptional),
102+
returns(BindOptionalType))),
89103
hasArgument(0, OptionalDerefMatcher))),
90104
unless(anyOf(hasAncestor(typeLoc()),
91105
hasAncestor(expr(matchers::hasUnevaluatedContext())))))

clang-tools-extra/docs/ReleaseNotes.rst

+4
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,10 @@ Changes in existing checks
124124
no longer be needed and will be removed. Also fixing false positive from
125125
const reference accessors to objects containing optional member.
126126

127+
- Improved :doc:`bugprone-optional-value-conversion
128+
<clang-tidy/checks/bugprone/optional-value-conversion>` check to detect
129+
conversion in argument of ``std::make_optional``.
130+
127131
- Improved :doc:`bugprone-unsafe-functions
128132
<clang-tidy/checks/bugprone/unsafe-functions>` check to allow specifying
129133
additional C++ member functions to match.

clang-tools-extra/test/clang-tidy/checkers/bugprone/optional-value-conversion-construct-from-std.cpp

+13
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,19 @@ class unique_ptr {};
2727
template <typename type>
2828
class shared_ptr {};
2929

30+
template <typename T>
31+
class initializer_list {};
32+
3033
template <class T, class... Args> unique_ptr<T> make_unique(Args &&...args);
3134
template <class T, class... Args> shared_ptr<T> make_shared(Args &&...args);
3235

36+
template <class T>
37+
constexpr std::optional<__decay(T)> make_optional(T &&value);
38+
template <class T, class... Args>
39+
constexpr std::optional<T> make_optional(Args &&...args);
40+
template <class T, class U, class... Args>
41+
constexpr std::optional<T> make_optional(std::initializer_list<U> il, Args &&...args);
42+
3343
} // namespace std
3444

3545
struct A {
@@ -45,9 +55,12 @@ void invalid() {
4555
// 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]
4656
std::make_shared<std::optional<int>>(opt.value());
4757
// 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]
58+
std::make_optional(opt.value());
59+
// 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]
4860
}
4961

5062
void valid() {
5163
std::make_unique<A>(opt.value());
5264
std::make_shared<A>(opt.value());
65+
std::make_optional<int>(opt.value());
5366
}

0 commit comments

Comments
 (0)