Skip to content

Commit 547c574

Browse files
committed
Merge from 'main' to 'sycl-web' (59 commits)
CONFLICT (content): Merge conflict in llvm/lib/Passes/PassBuilderPipelines.cpp
2 parents 54fa040 + a134b06 commit 547c574

File tree

251 files changed

+7217
-3596
lines changed

Some content is hidden

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

251 files changed

+7217
-3596
lines changed

clang-tools-extra/clang-tidy/.clang-tidy

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ Checks: >
55
-bugprone-branch-clone,
66
-bugprone-easily-swappable-parameters,
77
-bugprone-narrowing-conversions,
8-
-bugprone-suspicious-stringview-data-usage,
98
-bugprone-unchecked-optional-access,
109
-bugprone-unused-return-value,
1110
modernize-*,

clang-tools-extra/clang-tidy/ClangTidyOptions.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ void yamlize(IO &IO, ClangTidyOptions::OptionMap &Val, bool,
9999
for (auto &Option : SortedOptions) {
100100
bool UseDefault = false;
101101
void *SaveInfo = nullptr;
102+
// Requires 'llvm::yaml::IO' to accept 'StringRef'
103+
// NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
102104
IO.preflightKey(Option.first.data(), true, false, UseDefault, SaveInfo);
103105
IO.scalarString(Option.second, needsQuotes(Option.second));
104106
IO.postflightKey(SaveInfo);
@@ -116,6 +118,8 @@ void yamlize(IO &IO, ClangTidyOptions::OptionMap &Val, bool,
116118
} else if (isa<MappingNode>(I.getCurrentNode())) {
117119
IO.beginMapping();
118120
for (StringRef Key : IO.keys()) {
121+
// Requires 'llvm::yaml::IO' to accept 'StringRef'
122+
// NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
119123
IO.mapRequired(Key.data(), Val[Key].Value);
120124
}
121125
IO.endMapping();

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "CopyConstructorInitCheck.h"
2424
#include "CrtpConstructorAccessibilityCheck.h"
2525
#include "DanglingHandleCheck.h"
26+
#include "DerivedMethodShadowingBaseMethodCheck.h"
2627
#include "DynamicStaticInitializersCheck.h"
2728
#include "EasilySwappableParametersCheck.h"
2829
#include "EmptyCatchCheck.h"
@@ -134,6 +135,8 @@ class BugproneModule : public ClangTidyModule {
134135
"bugprone-copy-constructor-init");
135136
CheckFactories.registerCheck<DanglingHandleCheck>(
136137
"bugprone-dangling-handle");
138+
CheckFactories.registerCheck<DerivedMethodShadowingBaseMethodCheck>(
139+
"bugprone-derived-method-shadowing-base-method");
137140
CheckFactories.registerCheck<DynamicStaticInitializersCheck>(
138141
"bugprone-dynamic-static-initializers");
139142
CheckFactories.registerCheck<EasilySwappableParametersCheck>(

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ add_clang_library(clangTidyBugproneModule STATIC
1919
CopyConstructorInitCheck.cpp
2020
CrtpConstructorAccessibilityCheck.cpp
2121
DanglingHandleCheck.cpp
22+
DerivedMethodShadowingBaseMethodCheck.cpp
2223
DynamicStaticInitializersCheck.cpp
2324
EasilySwappableParametersCheck.cpp
2425
EmptyCatchCheck.cpp
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
//===----------------------------------------------------------------------===//
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 "DerivedMethodShadowingBaseMethodCheck.h"
10+
#include "clang/ASTMatchers/ASTMatchFinder.h"
11+
#include "clang/ASTMatchers/ASTMatchers.h"
12+
13+
using namespace clang::ast_matchers;
14+
15+
namespace clang::tidy::bugprone {
16+
17+
static bool sameBasicType(const ParmVarDecl *Lhs, const ParmVarDecl *Rhs) {
18+
return Lhs && Rhs &&
19+
Lhs->getType()
20+
.getCanonicalType()
21+
.getNonReferenceType()
22+
.getUnqualifiedType() == Rhs->getType()
23+
.getCanonicalType()
24+
.getNonReferenceType()
25+
.getUnqualifiedType();
26+
}
27+
28+
static bool namesCollide(const CXXMethodDecl &Lhs, const CXXMethodDecl &Rhs) {
29+
if (Lhs.getNameAsString() != Rhs.getNameAsString())
30+
return false;
31+
if (Lhs.isConst() != Rhs.isConst())
32+
return false;
33+
if (Lhs.getNumParams() != Rhs.getNumParams())
34+
return false;
35+
for (unsigned int It = 0; It < Lhs.getNumParams(); ++It)
36+
if (!sameBasicType(Lhs.getParamDecl(It), Rhs.getParamDecl(It)))
37+
return false;
38+
return true;
39+
}
40+
41+
namespace {
42+
43+
AST_MATCHER(CXXMethodDecl, nameCollidesWithMethodInBase) {
44+
const CXXRecordDecl *DerivedClass = Node.getParent();
45+
for (const auto &Base : DerivedClass->bases()) {
46+
llvm::SmallVector<const CXXBaseSpecifier *, 8> Stack;
47+
Stack.push_back(&Base);
48+
while (!Stack.empty()) {
49+
const CXXBaseSpecifier *CurrentBaseSpec = Stack.back();
50+
Stack.pop_back();
51+
52+
if (CurrentBaseSpec->getAccessSpecifier() ==
53+
clang::AccessSpecifier::AS_private)
54+
continue;
55+
56+
const CXXRecordDecl *CurrentRecord =
57+
CurrentBaseSpec->getType()->getAsCXXRecordDecl();
58+
if (!CurrentRecord)
59+
continue;
60+
61+
// For multiple inheritance, we ignore only the bases that come from the
62+
// std:: namespace
63+
if (CurrentRecord->isInStdNamespace())
64+
continue;
65+
66+
for (const auto &BaseMethod : CurrentRecord->methods()) {
67+
if (namesCollide(*BaseMethod, Node)) {
68+
ast_matchers::internal::BoundNodesTreeBuilder Result(*Builder);
69+
Builder->setBinding("base_method",
70+
clang::DynTypedNode::create(*BaseMethod));
71+
return true;
72+
}
73+
}
74+
75+
for (const auto &SubBase : CurrentRecord->bases())
76+
Stack.push_back(&SubBase);
77+
}
78+
}
79+
return false;
80+
}
81+
82+
// Same as clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.cpp,
83+
// similar matchers are used elsewhere in LLVM
84+
AST_MATCHER(CXXMethodDecl, isOutOfLine) { return Node.isOutOfLine(); }
85+
86+
} // namespace
87+
88+
DerivedMethodShadowingBaseMethodCheck::DerivedMethodShadowingBaseMethodCheck(
89+
StringRef Name, ClangTidyContext *Context)
90+
: ClangTidyCheck(Name, Context) {}
91+
92+
void DerivedMethodShadowingBaseMethodCheck::registerMatchers(
93+
MatchFinder *Finder) {
94+
Finder->addMatcher(
95+
cxxMethodDecl(
96+
unless(anyOf(isOutOfLine(), isStaticStorageClass(), isImplicit(),
97+
cxxConstructorDecl(), isOverride(), isPrivate(),
98+
// isFinal(), //included with isOverride,
99+
// Templates are not handled yet
100+
ast_matchers::isTemplateInstantiation(),
101+
ast_matchers::isExplicitTemplateSpecialization())),
102+
ofClass(cxxRecordDecl(isDerivedFrom(cxxRecordDecl()))
103+
.bind("derived_class")),
104+
nameCollidesWithMethodInBase())
105+
.bind("shadowing_method"),
106+
this);
107+
}
108+
109+
void DerivedMethodShadowingBaseMethodCheck::check(
110+
const MatchFinder::MatchResult &Result) {
111+
const auto *ShadowingMethod =
112+
Result.Nodes.getNodeAs<CXXMethodDecl>("shadowing_method");
113+
const auto *DerivedClass =
114+
Result.Nodes.getNodeAs<CXXRecordDecl>("derived_class");
115+
const auto *BaseMethod = Result.Nodes.getNodeAs<CXXMethodDecl>("base_method");
116+
117+
if (!ShadowingMethod || !DerivedClass || !BaseMethod)
118+
llvm_unreachable("Required binding not found");
119+
120+
diag(ShadowingMethod->getBeginLoc(),
121+
"'%0' shadows method with the same name in class %1")
122+
<< ShadowingMethod->getQualifiedNameAsString() << BaseMethod->getParent();
123+
diag(BaseMethod->getBeginLoc(), "previous definition of %0 is here",
124+
DiagnosticIDs::Note)
125+
<< ShadowingMethod;
126+
}
127+
128+
} // namespace clang::tidy::bugprone
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//===----------------------------------------------------------------------===//
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_DERIVEDMETHODSHADOWINGBASEMETHODCHECK_H
10+
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_DERIVEDMETHODSHADOWINGBASEMETHODCHECK_H
11+
12+
#include "../ClangTidyCheck.h"
13+
14+
namespace clang::tidy::bugprone {
15+
16+
/// Checks that a derived class does not define the same (non virtual) method as
17+
/// a base class
18+
///
19+
/// For the user-facing documentation see:
20+
/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone/derived-method-shadowing-base-method.html
21+
class DerivedMethodShadowingBaseMethodCheck : public ClangTidyCheck {
22+
public:
23+
DerivedMethodShadowingBaseMethodCheck(StringRef Name,
24+
ClangTidyContext *Context);
25+
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
26+
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
27+
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
28+
return LangOpts.CPlusPlus;
29+
}
30+
std::optional<TraversalKind> getCheckTraversalKind() const override {
31+
return TK_IgnoreUnlessSpelledInSource;
32+
}
33+
};
34+
35+
} // namespace clang::tidy::bugprone
36+
37+
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_DERIVEDMETHODSHADOWINGBASEMETHODCHECK_H

clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ static bool bodyEmpty(const ASTContext *Context, const CompoundStmt *Body) {
204204
CharSourceRange::getCharRange(Body->getLBracLoc().getLocWithOffset(1),
205205
Body->getRBracLoc()),
206206
Context->getSourceManager(), Context->getLangOpts(), &Invalid);
207-
return !Invalid && std::strspn(Text.data(), " \t\r\n") == Text.size();
207+
return !Invalid && Text.ltrim(" \t\r\n").empty();
208208
}
209209

210210
UseEqualsDefaultCheck::UseEqualsDefaultCheck(StringRef Name,

clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -337,8 +337,7 @@ std::string IdentifierNamingCheck::HungarianNotation::getDeclTypeName(
337337

338338
// Remove keywords
339339
for (StringRef Kw : Keywords) {
340-
for (size_t Pos = 0;
341-
(Pos = Type.find(Kw.data(), Pos)) != std::string::npos;) {
340+
for (size_t Pos = 0; (Pos = Type.find(Kw, Pos)) != std::string::npos;) {
342341
Type.replace(Pos, Kw.size(), "");
343342
}
344343
}
@@ -373,7 +372,7 @@ std::string IdentifierNamingCheck::HungarianNotation::getDeclTypeName(
373372
" int", " char", " double", " long", " short"};
374373
bool RedundantRemoved = false;
375374
for (auto Kw : TailsOfMultiWordType) {
376-
size_t Pos = Type.rfind(Kw.data());
375+
size_t Pos = Type.rfind(Kw);
377376
if (Pos != std::string::npos) {
378377
const size_t PtrCount = getAsteriskCount(Type, ND);
379378
Type = Type.substr(0, Pos + Kw.size() + PtrCount);
@@ -602,9 +601,8 @@ std::string IdentifierNamingCheck::HungarianNotation::getDataTypePrefix(
602601
if (PtrCount > 0) {
603602
ModifiedTypeName = [&](std::string Str, StringRef From, StringRef To) {
604603
size_t StartPos = 0;
605-
while ((StartPos = Str.find(From.data(), StartPos)) !=
606-
std::string::npos) {
607-
Str.replace(StartPos, From.size(), To.data());
604+
while ((StartPos = Str.find(From, StartPos)) != std::string::npos) {
605+
Str.replace(StartPos, From.size(), To);
608606
StartPos += To.size();
609607
}
610608
return Str;

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,11 @@ New checks
163163
Detects default initialization (to 0) of variables with ``enum`` type where
164164
the enum has no enumerator with value of 0.
165165

166+
- New :doc:`bugprone-derived-method-shadowing-base-method
167+
<clang-tidy/checks/bugprone/derived-method-shadowing-base-method>` check.
168+
169+
Finds derived class methods that shadow a (non-virtual) base class method.
170+
166171
- New :doc:`cppcoreguidelines-pro-bounds-avoid-unchecked-container-access
167172
<clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-access>`
168173
check.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
.. title:: clang-tidy - bugprone-derived-method-shadowing-base-method
2+
3+
bugprone-derived-method-shadowing-base-method
4+
=============================================
5+
6+
Finds derived class methods that shadow a (non-virtual) base class method.
7+
8+
In order to be considered "shadowing", methods must have the same signature
9+
(i.e. the same name, same number of parameters, same parameter types, etc).
10+
Only checks public, non-templated methods.
11+
12+
The below example is bugprone because consumers of the ``Derived`` class will
13+
expect the ``reset`` method to do the work of ``Base::reset()`` in addition to extra
14+
work required to reset the ``Derived`` class. Common fixes include:
15+
16+
- Making the ``reset`` method polymorphic
17+
- Re-naming ``Derived::reset`` if it's not meant to intersect with ``Base::reset``
18+
- Using ``using Base::reset`` to change the access specifier
19+
20+
This is also a violation of the Liskov Substitution Principle.
21+
22+
.. code-block:: c++
23+
24+
struct Base {
25+
void reset() {/* reset the base class */};
26+
};
27+
28+
struct Derived : public Base {
29+
void reset() {/* reset the derived class, but not the base class */};
30+
};

0 commit comments

Comments
 (0)