-
Notifications
You must be signed in to change notification settings - Fork 14.4k
[clang-tidy]detecting conversion directly by make_unique
and make_shared
in bugprone-optional-value-conversion
#119371
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…shared` in bugprone-optional-value-conversion Inspired by llvm#110964
@llvm/pr-subscribers-clang-tools-extra @llvm/pr-subscribers-clang-tidy Author: Congcong Cai (HerrCai0907) ChangesInspired by #110964 Full diff: https://github.com/llvm/llvm-project/pull/119371.diff 3 Files Affected:
diff --git a/clang-tools-extra/clang-tidy/bugprone/OptionalValueConversionCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/OptionalValueConversionCheck.cpp
index f2ff27d85fb004..0ed8c8d00f4222 100644
--- a/clang-tools-extra/clang-tidy/bugprone/OptionalValueConversionCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/OptionalValueConversionCheck.cpp
@@ -12,20 +12,44 @@
#include "../utils/OptionsUtils.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include <array>
using namespace clang::ast_matchers;
+using clang::ast_matchers::internal::Matcher;
namespace clang::tidy::bugprone {
namespace {
-AST_MATCHER_P(QualType, hasCleanType, ast_matchers::internal::Matcher<QualType>,
- InnerMatcher) {
+AST_MATCHER_P(QualType, hasCleanType, Matcher<QualType>, InnerMatcher) {
return InnerMatcher.matches(
Node.getNonReferenceType().getUnqualifiedType().getCanonicalType(),
Finder, Builder);
}
+AST_MATCHER_P2(Expr, constructFrom, Matcher<QualType>, TypeMatcher,
+ Matcher<Expr>, ArgumentMatcher) {
+ std::array<StringRef, 2> NameList{
+ "::std::make_unique",
+ "::std::make_shared",
+ };
+ return expr(anyOf(
+ // construct optional
+ cxxConstructExpr(argumentCountIs(1U), hasType(TypeMatcher),
+ hasArgument(0U, ArgumentMatcher)),
+ // known template methods in std
+ callExpr(
+ argumentCountIs(1),
+ callee(functionDecl(
+ matchers::matchesAnyListedName(NameList),
+ hasTemplateArgument(0, refersToType(TypeMatcher)))),
+ hasArgument(0, ArgumentMatcher))),
+ unless(
+ anyOf(hasAncestor(typeLoc()),
+ hasAncestor(expr(matchers::hasUnevaluatedContext())))))
+ .matches(Node, Finder, Builder);
+}
+
} // namespace
OptionalValueConversionCheck::OptionalValueConversionCheck(
@@ -67,12 +91,9 @@ void OptionalValueConversionCheck::registerMatchers(MatchFinder *Finder) {
callExpr(argumentCountIs(1), callee(functionDecl(hasName("::std::move"))),
hasArgument(0, ignoringImpCasts(OptionalDereferenceMatcher)));
Finder->addMatcher(
- cxxConstructExpr(
- argumentCountIs(1U), hasType(BindOptionalType),
- hasArgument(0U, ignoringImpCasts(anyOf(OptionalDereferenceMatcher,
- StdMoveCallMatcher))),
- unless(anyOf(hasAncestor(typeLoc()),
- hasAncestor(expr(matchers::hasUnevaluatedContext())))))
+ expr(constructFrom(BindOptionalType,
+ ignoringImpCasts(anyOf(OptionalDereferenceMatcher,
+ StdMoveCallMatcher))))
.bind("expr"),
this);
}
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index b2b66dca6ccf85..9c499159b73c7b 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -176,6 +176,10 @@ Changes in existing checks
<clang-tidy/checks/bugprone/forwarding-reference-overload>` check by fixing
a crash when determining if an ``enable_if[_t]`` was found.
+- Improved :doc:`bugprone-optional-value-conversion
+ <clang-tidy/checks/bugprone/optional-value-conversion>` to support detecting
+ conversion directly by ``std::make_unique`` and ``std::make_shared``.
+
- Improved :doc:`bugprone-posix-return
<clang-tidy/checks/bugprone/posix-return>` check to support integer literals
as LHS and posix call as RHS of comparison.
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
new file mode 100644
index 00000000000000..768ab1ce014cec
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/optional-value-conversion-construct-from-std.cpp
@@ -0,0 +1,53 @@
+// RUN: %check_clang_tidy -std=c++17-or-later %s bugprone-optional-value-conversion %t
+
+namespace std {
+template <typename T> struct optional {
+ constexpr optional() noexcept;
+ constexpr optional(T &&) noexcept;
+ constexpr optional(const T &) noexcept;
+ template <typename U> constexpr optional(U &&) noexcept;
+ const T &operator*() const;
+ T *operator->();
+ const T *operator->() const;
+ T &operator*();
+ const T &value() const;
+ T &value();
+ const T &get() const;
+ T &get();
+ T value_or(T) const;
+};
+
+template <class T> T &&move(T &x) { return static_cast<T &&>(x); }
+
+template <typename T> class default_delete {};
+
+template <typename type, typename Deleter = std::default_delete<type>>
+class unique_ptr {};
+
+template <typename type>
+class shared_ptr {};
+
+template <class T, class... Args> unique_ptr<T> make_unique(Args &&...args);
+template <class T, class... Args> shared_ptr<T> make_shared(Args &&...args);
+
+} // namespace std
+
+struct A {
+ explicit A (int);
+};
+std::optional<int> opt;
+
+void invalid() {
+ std::make_unique<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]
+ using A = std::optional<int>;
+ std::make_unique<A>(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_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]
+}
+
+void valid() {
+ std::make_unique<A>(opt.value());
+ std::make_shared<A>(opt.value());
+}
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: Probably also std::make_optional could be supported.
Please improve performance - avoid creating temporary matchers on every match.
Except above, looks fine.
clang-tools-extra/clang-tidy/bugprone/OptionalValueConversionCheck.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/clang-tidy/bugprone/OptionalValueConversionCheck.cpp
Outdated
Show resolved
Hide resolved
Can the logic for implementing this also be used to address #86447 (comment)? |
I think this kind model of stl can be reused in other check. but i have no idea to make it more generic. |
I will do it in separated PR since std::make_optional is more complex stuff. see #119554 |
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/190/builds/11188 Here is the relevant piece of the build log for the reference
|
Inspired by #110964