Skip to content
This repository was archived by the owner on Sep 15, 2025. It is now read-only.

Commit ca668ac

Browse files
SC llvm teammariusz-sikora-at-amd
authored andcommitted
Merged main:cce35994bb72 into amd-gfx:b53c56f743f7
Local branch amd-gfx b53c56f Merged main:f7b09516e466 into amd-gfx:e631f76db5ef Remote branch main cce3599 [Object] Fix grammar mistake in the comment
2 parents b53c56f + cce3599 commit ca668ac

File tree

260 files changed

+9020
-4915
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

260 files changed

+9020
-4915
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
#include "NoEscapeCheck.h"
4545
#include "NonZeroEnumToBoolConversionCheck.h"
4646
#include "NotNullTerminatedResultCheck.h"
47+
#include "OptionalValueConversionCheck.h"
4748
#include "ParentVirtualCallCheck.h"
4849
#include "PosixReturnCheck.h"
4950
#include "RedundantBranchConditionCheck.h"
@@ -150,6 +151,8 @@ class BugproneModule : public ClangTidyModule {
150151
"bugprone-multiple-new-in-one-expression");
151152
CheckFactories.registerCheck<MultipleStatementMacroCheck>(
152153
"bugprone-multiple-statement-macro");
154+
CheckFactories.registerCheck<OptionalValueConversionCheck>(
155+
"bugprone-optional-value-conversion");
153156
CheckFactories.registerCheck<RedundantBranchConditionCheck>(
154157
"bugprone-redundant-branch-condition");
155158
CheckFactories.registerCheck<cppcoreguidelines::NarrowingConversionsCheck>(

clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ add_clang_library(clangTidyBugproneModule
4040
NoEscapeCheck.cpp
4141
NonZeroEnumToBoolConversionCheck.cpp
4242
NotNullTerminatedResultCheck.cpp
43+
OptionalValueConversionCheck.cpp
4344
ParentVirtualCallCheck.cpp
4445
PosixReturnCheck.cpp
4546
RedundantBranchConditionCheck.cpp
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
//===--- OptionalValueConversionCheck.cpp - clang-tidy --------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "OptionalValueConversionCheck.h"
10+
#include "../utils/LexerUtils.h"
11+
#include "../utils/Matchers.h"
12+
#include "../utils/OptionsUtils.h"
13+
#include "clang/AST/ASTContext.h"
14+
#include "clang/ASTMatchers/ASTMatchFinder.h"
15+
16+
using namespace clang::ast_matchers;
17+
18+
namespace clang::tidy::bugprone {
19+
20+
namespace {
21+
22+
AST_MATCHER_P(QualType, hasCleanType, ast_matchers::internal::Matcher<QualType>,
23+
InnerMatcher) {
24+
return InnerMatcher.matches(
25+
Node.getNonReferenceType().getUnqualifiedType().getCanonicalType(),
26+
Finder, Builder);
27+
}
28+
29+
} // namespace
30+
31+
OptionalValueConversionCheck::OptionalValueConversionCheck(
32+
StringRef Name, ClangTidyContext *Context)
33+
: ClangTidyCheck(Name, Context),
34+
OptionalTypes(utils::options::parseStringList(
35+
Options.get("OptionalTypes",
36+
"::std::optional;::absl::optional;::boost::optional"))),
37+
ValueMethods(utils::options::parseStringList(
38+
Options.get("ValueMethods", "::value$;::get$"))) {}
39+
40+
std::optional<TraversalKind>
41+
OptionalValueConversionCheck::getCheckTraversalKind() const {
42+
return TK_AsIs;
43+
}
44+
45+
void OptionalValueConversionCheck::registerMatchers(MatchFinder *Finder) {
46+
auto ConstructTypeMatcher =
47+
qualType(hasCleanType(qualType().bind("optional-type")));
48+
49+
auto CallTypeMatcher =
50+
qualType(hasCleanType(equalsBoundNode("optional-type")));
51+
52+
auto OptionalDereferenceMatcher = callExpr(
53+
anyOf(
54+
cxxOperatorCallExpr(hasOverloadedOperatorName("*"),
55+
hasUnaryOperand(hasType(CallTypeMatcher)))
56+
.bind("op-call"),
57+
cxxMemberCallExpr(thisPointerType(CallTypeMatcher),
58+
callee(cxxMethodDecl(anyOf(
59+
hasOverloadedOperatorName("*"),
60+
matchers::matchesAnyListedName(ValueMethods)))))
61+
.bind("member-call")),
62+
hasType(qualType().bind("value-type")));
63+
64+
auto StdMoveCallMatcher =
65+
callExpr(argumentCountIs(1), callee(functionDecl(hasName("::std::move"))),
66+
hasArgument(0, ignoringImpCasts(OptionalDereferenceMatcher)));
67+
Finder->addMatcher(
68+
cxxConstructExpr(
69+
argumentCountIs(1U),
70+
hasDeclaration(cxxConstructorDecl(
71+
ofClass(matchers::matchesAnyListedName(OptionalTypes)))),
72+
hasType(ConstructTypeMatcher),
73+
hasArgument(0U, ignoringImpCasts(anyOf(OptionalDereferenceMatcher,
74+
StdMoveCallMatcher))))
75+
.bind("expr"),
76+
this);
77+
}
78+
79+
void OptionalValueConversionCheck::storeOptions(
80+
ClangTidyOptions::OptionMap &Opts) {
81+
Options.store(Opts, "OptionalTypes",
82+
utils::options::serializeStringList(OptionalTypes));
83+
Options.store(Opts, "ValueMethods",
84+
utils::options::serializeStringList(ValueMethods));
85+
}
86+
87+
void OptionalValueConversionCheck::check(
88+
const MatchFinder::MatchResult &Result) {
89+
const auto *MatchedExpr = Result.Nodes.getNodeAs<Expr>("expr");
90+
const auto *OptionalType = Result.Nodes.getNodeAs<QualType>("optional-type");
91+
const auto *ValueType = Result.Nodes.getNodeAs<QualType>("value-type");
92+
93+
diag(MatchedExpr->getExprLoc(),
94+
"conversion from %0 into %1 and back into %0, remove potentially "
95+
"error-prone optional dereference")
96+
<< *OptionalType << ValueType->getUnqualifiedType();
97+
98+
if (const auto *OperatorExpr =
99+
Result.Nodes.getNodeAs<CXXOperatorCallExpr>("op-call")) {
100+
diag(OperatorExpr->getExprLoc(), "remove '*' to silence this warning",
101+
DiagnosticIDs::Note)
102+
<< FixItHint::CreateRemoval(CharSourceRange::getTokenRange(
103+
OperatorExpr->getBeginLoc(), OperatorExpr->getExprLoc()));
104+
return;
105+
}
106+
if (const auto *CallExpr =
107+
Result.Nodes.getNodeAs<CXXMemberCallExpr>("member-call")) {
108+
const SourceLocation Begin =
109+
utils::lexer::getPreviousToken(CallExpr->getExprLoc(),
110+
*Result.SourceManager, getLangOpts())
111+
.getLocation();
112+
auto Diag =
113+
diag(CallExpr->getExprLoc(),
114+
"remove call to %0 to silence this warning", DiagnosticIDs::Note);
115+
Diag << CallExpr->getMethodDecl()
116+
<< FixItHint::CreateRemoval(
117+
CharSourceRange::getTokenRange(Begin, CallExpr->getEndLoc()));
118+
if (const auto *Member =
119+
llvm::dyn_cast<MemberExpr>(CallExpr->getCallee()->IgnoreImplicit());
120+
Member && Member->isArrow())
121+
Diag << FixItHint::CreateInsertion(CallExpr->getBeginLoc(), "*");
122+
return;
123+
}
124+
}
125+
126+
} // namespace clang::tidy::bugprone
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
//===--- OptionalValueConversionCheck.h - clang-tidy ------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_OPTIONALVALUECONVERSIONCHECK_H
10+
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_OPTIONALVALUECONVERSIONCHECK_H
11+
12+
#include "../ClangTidyCheck.h"
13+
#include <vector>
14+
15+
namespace clang::tidy::bugprone {
16+
17+
/// Detects potentially unintentional and redundant conversions where a value is
18+
/// extracted from an optional-like type and then used to create a new instance
19+
/// of the same optional-like type.
20+
///
21+
/// For the user-facing documentation see:
22+
/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone/optional-value-conversion.html
23+
class OptionalValueConversionCheck : public ClangTidyCheck {
24+
public:
25+
OptionalValueConversionCheck(StringRef Name, ClangTidyContext *Context);
26+
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
27+
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
28+
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
29+
std::optional<TraversalKind> getCheckTraversalKind() const override;
30+
31+
private:
32+
std::vector<StringRef> OptionalTypes;
33+
std::vector<StringRef> ValueMethods;
34+
};
35+
36+
} // namespace clang::tidy::bugprone
37+
38+
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_OPTIONALVALUECONVERSIONCHECK_H

clang-tools-extra/clangd/IncludeCleaner.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ bool isIgnored(llvm::StringRef HeaderPath, HeaderFilter IgnoreHeaders) {
7171
bool mayConsiderUnused(
7272
const Inclusion &Inc, ParsedAST &AST,
7373
const include_cleaner::PragmaIncludes *PI) {
74+
if (PI && PI->shouldKeep(Inc.HashLine + 1))
75+
return false;
7476
// FIXME(kirillbobyrev): We currently do not support the umbrella headers.
7577
// System headers are likely to be standard library headers.
7678
// Until we have good support for umbrella headers, don't warn about them.
@@ -82,8 +84,6 @@ bool mayConsiderUnused(
8284
AST.getIncludeStructure().getRealPath(HID));
8385
assert(FE);
8486
if (PI) {
85-
if (PI->shouldKeep(Inc.HashLine + 1))
86-
return false;
8787
// Check if main file is the public interface for a private header. If so we
8888
// shouldn't diagnose it as unused.
8989
if (auto PHeader = PI->getPublic(*FE); !PHeader.empty()) {

clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ TEST(IncludeCleaner, StdlibUnused) {
7878
auto TU = TestTU::withCode(R"cpp(
7979
#include <list>
8080
#include <queue>
81+
#include <vector> // IWYU pragma: keep
82+
#include <string> // IWYU pragma: export
8183
std::list<int> x;
8284
)cpp");
8385
// Layout of std library impl is not relevant.
@@ -86,10 +88,13 @@ TEST(IncludeCleaner, StdlibUnused) {
8688
namespace std {
8789
template <typename> class list {};
8890
template <typename> class queue {};
91+
template <typename> class vector {};
8992
}
9093
)cpp";
9194
TU.AdditionalFiles["list"] = "#include <bits>";
9295
TU.AdditionalFiles["queue"] = "#include <bits>";
96+
TU.AdditionalFiles["vector"] = "#include <bits>";
97+
TU.AdditionalFiles["string"] = "#include <bits>";
9398
TU.ExtraArgs = {"-isystem", testRoot()};
9499
auto AST = TU.build();
95100
IncludeCleanerFindings Findings = computeIncludeCleanerFindings(AST);

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,13 @@ New checks
129129
Detects implicit conversions between pointers of different levels of
130130
indirection.
131131

132+
- New :doc:`bugprone-optional-value-conversion
133+
<clang-tidy/checks/bugprone/optional-value-conversion>` check.
134+
135+
Detects potentially unintentional and redundant conversions where a value is
136+
extracted from an optional-like type and then used to create a new instance
137+
of the same optional-like type.
138+
132139
- New :doc:`modernize-use-constraints
133140
<clang-tidy/checks/modernize/use-constraints>` check.
134141

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
.. title:: clang-tidy - bugprone-optional-value-conversion
2+
3+
bugprone-optional-value-conversion
4+
==================================
5+
6+
Detects potentially unintentional and redundant conversions where a value is
7+
extracted from an optional-like type and then used to create a new instance of
8+
the same optional-like type.
9+
10+
These conversions might be the result of developer oversight, leftovers from
11+
code refactoring, or other situations that could lead to unintended exceptions
12+
or cases where the resulting optional is always initialized, which might be
13+
unexpected behavior.
14+
15+
To illustrate, consider the following problematic code snippet:
16+
17+
.. code-block:: c++
18+
19+
#include <optional>
20+
21+
void print(std::optional<int>);
22+
23+
int main()
24+
{
25+
std::optional<int> opt;
26+
// ...
27+
28+
// Unintentional conversion from std::optional<int> to int and back to
29+
// std::optional<int>:
30+
print(opt.value());
31+
32+
// ...
33+
}
34+
35+
A better approach would be to directly pass ``opt`` to the ``print`` function
36+
without extracting its value:
37+
38+
.. code-block:: c++
39+
40+
#include <optional>
41+
42+
void print(std::optional<int>);
43+
44+
int main()
45+
{
46+
std::optional<int> opt;
47+
// ...
48+
49+
// Proposed code: Directly pass the std::optional<int> to the print
50+
// function.
51+
print(opt);
52+
53+
// ...
54+
}
55+
56+
By passing ``opt`` directly to the print function, unnecessary conversions are
57+
avoided, and potential unintended behavior or exceptions are minimized.
58+
59+
Value extraction using ``operator *`` is matched by default.
60+
The support for non-standard optional types such as ``boost::optional`` or
61+
``absl::optional`` may be limited.
62+
63+
Options:
64+
--------
65+
66+
.. option:: OptionalTypes
67+
68+
Semicolon-separated list of (fully qualified) optional type names or regular
69+
expressions that match the optional types.
70+
Default value is `::std::optional;::absl::optional;::boost::optional`.
71+
72+
.. option:: ValueMethods
73+
74+
Semicolon-separated list of (fully qualified) method names or regular
75+
expressions that match the methods.
76+
Default value is `::value$;::get$`.

clang-tools-extra/docs/clang-tidy/checks/list.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ Clang-Tidy Checks
110110
`bugprone-no-escape <bugprone/no-escape.html>`_,
111111
`bugprone-non-zero-enum-to-bool-conversion <bugprone/non-zero-enum-to-bool-conversion.html>`_,
112112
`bugprone-not-null-terminated-result <bugprone/not-null-terminated-result.html>`_, "Yes"
113+
`bugprone-optional-value-conversion <bugprone/optional-value-conversion.html>`_, "Yes"
113114
`bugprone-parent-virtual-call <bugprone/parent-virtual-call.html>`_, "Yes"
114115
`bugprone-posix-return <bugprone/posix-return.html>`_, "Yes"
115116
`bugprone-redundant-branch-condition <bugprone/redundant-branch-condition.html>`_, "Yes"

0 commit comments

Comments
 (0)