annotate clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.cpp @ 266:00f31e85ec16 default tip

Added tag current for changeset 31d058e83c98
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Sat, 14 Oct 2023 10:13:55 +0900
parents 1f2b6ac9f198
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
150
anatofuz
parents:
diff changeset
1 //===--- ContainerSizeEmptyCheck.cpp - clang-tidy -------------------------===//
anatofuz
parents:
diff changeset
2 //
anatofuz
parents:
diff changeset
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
anatofuz
parents:
diff changeset
4 // See https://llvm.org/LICENSE.txt for license information.
anatofuz
parents:
diff changeset
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
anatofuz
parents:
diff changeset
6 //
anatofuz
parents:
diff changeset
7 //===----------------------------------------------------------------------===//
anatofuz
parents:
diff changeset
8 #include "ContainerSizeEmptyCheck.h"
anatofuz
parents:
diff changeset
9 #include "../utils/ASTUtils.h"
anatofuz
parents:
diff changeset
10 #include "../utils/Matchers.h"
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
11 #include "../utils/OptionsUtils.h"
150
anatofuz
parents:
diff changeset
12 #include "clang/AST/ASTContext.h"
anatofuz
parents:
diff changeset
13 #include "clang/ASTMatchers/ASTMatchers.h"
anatofuz
parents:
diff changeset
14 #include "clang/Lex/Lexer.h"
anatofuz
parents:
diff changeset
15 #include "llvm/ADT/StringRef.h"
anatofuz
parents:
diff changeset
16
anatofuz
parents:
diff changeset
17 using namespace clang::ast_matchers;
anatofuz
parents:
diff changeset
18
anatofuz
parents:
diff changeset
19 namespace clang {
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
20 namespace ast_matchers {
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
21
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
22 AST_POLYMORPHIC_MATCHER_P2(hasAnyArgumentWithParam,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
23 AST_POLYMORPHIC_SUPPORTED_TYPES(CallExpr,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
24 CXXConstructExpr),
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
25 internal::Matcher<Expr>, ArgMatcher,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
26 internal::Matcher<ParmVarDecl>, ParamMatcher) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
27 BoundNodesTreeBuilder Result;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
28 // The first argument of an overloaded member operator is the implicit object
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
29 // argument of the method which should not be matched against a parameter, so
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
30 // we skip over it here.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
31 BoundNodesTreeBuilder Matches;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
32 unsigned ArgIndex = cxxOperatorCallExpr(callee(cxxMethodDecl()))
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
33 .matches(Node, Finder, &Matches)
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
34 ? 1
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
35 : 0;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
36 int ParamIndex = 0;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
37 for (; ArgIndex < Node.getNumArgs(); ++ArgIndex) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
38 BoundNodesTreeBuilder ArgMatches(*Builder);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
39 if (ArgMatcher.matches(*(Node.getArg(ArgIndex)->IgnoreParenCasts()), Finder,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
40 &ArgMatches)) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
41 BoundNodesTreeBuilder ParamMatches(ArgMatches);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
42 if (expr(anyOf(cxxConstructExpr(hasDeclaration(cxxConstructorDecl(
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
43 hasParameter(ParamIndex, ParamMatcher)))),
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
44 callExpr(callee(functionDecl(
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
45 hasParameter(ParamIndex, ParamMatcher))))))
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
46 .matches(Node, Finder, &ParamMatches)) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
47 Result.addMatch(ParamMatches);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
48 *Builder = std::move(Result);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
49 return true;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
50 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
51 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
52 ++ParamIndex;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
53 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
54 return false;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
55 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
56
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
57 AST_MATCHER(Expr, usedInBooleanContext) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
58 const char *ExprName = "__booleanContextExpr";
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
59 auto Result =
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
60 expr(expr().bind(ExprName),
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
61 anyOf(hasParent(
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
62 mapAnyOf(varDecl, fieldDecl).with(hasType(booleanType()))),
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
63 hasParent(cxxConstructorDecl(
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
64 hasAnyConstructorInitializer(cxxCtorInitializer(
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
65 withInitializer(expr(equalsBoundNode(ExprName))),
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
66 forField(hasType(booleanType())))))),
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
67 hasParent(stmt(anyOf(
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
68 explicitCastExpr(hasDestinationType(booleanType())),
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
69 mapAnyOf(ifStmt, doStmt, whileStmt, forStmt,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
70 conditionalOperator)
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
71 .with(hasCondition(expr(equalsBoundNode(ExprName)))),
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
72 parenListExpr(hasParent(varDecl(hasType(booleanType())))),
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
73 parenExpr(hasParent(
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
74 explicitCastExpr(hasDestinationType(booleanType())))),
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
75 returnStmt(forFunction(returns(booleanType()))),
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
76 cxxUnresolvedConstructExpr(hasType(booleanType())),
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
77 invocation(hasAnyArgumentWithParam(
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
78 expr(equalsBoundNode(ExprName)),
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
79 parmVarDecl(hasType(booleanType())))),
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
80 binaryOperator(hasAnyOperatorName("&&", "||")),
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
81 unaryOperator(hasOperatorName("!")).bind("NegOnSize"))))))
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
82 .matches(Node, Finder, Builder);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
83 Builder->removeBindings([ExprName](const BoundNodesMap &Nodes) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
84 return Nodes.getNode(ExprName).getNodeKind().isNone();
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
85 });
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
86 return Result;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
87 }
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
88
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
89 AST_MATCHER(CXXConstructExpr, isDefaultConstruction) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
90 return Node.getConstructor()->isDefaultConstructor();
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
91 }
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
92
236
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
93 AST_MATCHER(QualType, isIntegralType) {
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
94 return Node->isIntegralType(Finder->getASTContext());
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
95 }
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
96
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
97 } // namespace ast_matchers
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
98 namespace tidy::readability {
150
anatofuz
parents:
diff changeset
99
236
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
100 using utils::isBinaryOrTernary;
150
anatofuz
parents:
diff changeset
101
anatofuz
parents:
diff changeset
102 ContainerSizeEmptyCheck::ContainerSizeEmptyCheck(StringRef Name,
anatofuz
parents:
diff changeset
103 ClangTidyContext *Context)
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
104 : ClangTidyCheck(Name, Context),
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
105 ExcludedComparisonTypes(utils::options::parseStringList(
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
106 Options.get("ExcludedComparisonTypes", "::std::array"))) {}
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
107
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
108 void ContainerSizeEmptyCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
109 Options.store(Opts, "ExcludedComparisonTypes",
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
110 utils::options::serializeStringList(ExcludedComparisonTypes));
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
111 }
150
anatofuz
parents:
diff changeset
112
anatofuz
parents:
diff changeset
113 void ContainerSizeEmptyCheck::registerMatchers(MatchFinder *Finder) {
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
114 const auto ValidContainerRecord = cxxRecordDecl(isSameOrDerivedFrom(
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
115 namedDecl(
236
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
116 has(cxxMethodDecl(
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
117 isConst(), parameterCountIs(0), isPublic(), hasName("size"),
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
118 returns(qualType(isIntegralType(), unless(booleanType()))))
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
119 .bind("size")),
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
120 has(cxxMethodDecl(isConst(), parameterCountIs(0), isPublic(),
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
121 hasName("empty"), returns(booleanType()))
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
122 .bind("empty")))
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
123 .bind("container")));
150
anatofuz
parents:
diff changeset
124
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
125 const auto ValidContainerNonTemplateType =
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
126 qualType(hasUnqualifiedDesugaredType(
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
127 recordType(hasDeclaration(ValidContainerRecord))));
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
128 const auto ValidContainerTemplateType =
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
129 qualType(hasUnqualifiedDesugaredType(templateSpecializationType(
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
130 hasDeclaration(classTemplateDecl(has(ValidContainerRecord))))));
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
131
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
132 const auto ValidContainer = qualType(
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
133 anyOf(ValidContainerNonTemplateType, ValidContainerTemplateType));
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
134
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
135 const auto WrongUse =
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
136 anyOf(hasParent(binaryOperator(
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
137 isComparisonOperator(),
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
138 hasEitherOperand(anyOf(integerLiteral(equals(1)),
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
139 integerLiteral(equals(0)))))
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
140 .bind("SizeBinaryOp")),
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
141 usedInBooleanContext());
150
anatofuz
parents:
diff changeset
142
anatofuz
parents:
diff changeset
143 Finder->addMatcher(
anatofuz
parents:
diff changeset
144 cxxMemberCallExpr(on(expr(anyOf(hasType(ValidContainer),
anatofuz
parents:
diff changeset
145 hasType(pointsTo(ValidContainer)),
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
146 hasType(references(ValidContainer))))
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
147 .bind("MemberCallObject")),
150
anatofuz
parents:
diff changeset
148 callee(cxxMethodDecl(hasName("size"))), WrongUse,
anatofuz
parents:
diff changeset
149 unless(hasAncestor(cxxMethodDecl(
anatofuz
parents:
diff changeset
150 ofClass(equalsBoundNode("container"))))))
anatofuz
parents:
diff changeset
151 .bind("SizeCallExpr"),
anatofuz
parents:
diff changeset
152 this);
anatofuz
parents:
diff changeset
153
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
154 Finder->addMatcher(
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
155 callExpr(has(cxxDependentScopeMemberExpr(
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
156 hasObjectExpression(
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
157 expr(anyOf(hasType(ValidContainer),
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
158 hasType(pointsTo(ValidContainer)),
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
159 hasType(references(ValidContainer))))
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
160 .bind("MemberCallObject")),
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
161 hasMemberName("size"))),
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
162 WrongUse,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
163 unless(hasAncestor(
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
164 cxxMethodDecl(ofClass(equalsBoundNode("container"))))))
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
165 .bind("SizeCallExpr"),
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
166 this);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
167
150
anatofuz
parents:
diff changeset
168 // Comparison to empty string or empty constructor.
anatofuz
parents:
diff changeset
169 const auto WrongComparend = anyOf(
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
170 stringLiteral(hasSize(0)), cxxConstructExpr(isDefaultConstruction()),
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
171 cxxUnresolvedConstructExpr(argumentCountIs(0)));
150
anatofuz
parents:
diff changeset
172 // Match the object being compared.
anatofuz
parents:
diff changeset
173 const auto STLArg =
anatofuz
parents:
diff changeset
174 anyOf(unaryOperator(
anatofuz
parents:
diff changeset
175 hasOperatorName("*"),
anatofuz
parents:
diff changeset
176 hasUnaryOperand(
anatofuz
parents:
diff changeset
177 expr(hasType(pointsTo(ValidContainer))).bind("Pointee"))),
anatofuz
parents:
diff changeset
178 expr(hasType(ValidContainer)).bind("STLObject"));
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
179
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
180 const auto ExcludedComparisonTypesMatcher = qualType(anyOf(
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
181 hasDeclaration(
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
182 cxxRecordDecl(matchers::matchesAnyListedName(ExcludedComparisonTypes))
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
183 .bind("excluded")),
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
184 hasCanonicalType(hasDeclaration(
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
185 cxxRecordDecl(matchers::matchesAnyListedName(ExcludedComparisonTypes))
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
186 .bind("excluded")))));
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
187 const auto SameExcludedComparisonTypesMatcher =
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
188 qualType(anyOf(hasDeclaration(cxxRecordDecl(equalsBoundNode("excluded"))),
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
189 hasCanonicalType(hasDeclaration(
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
190 cxxRecordDecl(equalsBoundNode("excluded"))))));
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
191
150
anatofuz
parents:
diff changeset
192 Finder->addMatcher(
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
193 binaryOperation(
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
194 hasAnyOperatorName("==", "!="), hasOperands(WrongComparend, STLArg),
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
195 unless(allOf(hasLHS(hasType(ExcludedComparisonTypesMatcher)),
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
196 hasRHS(hasType(SameExcludedComparisonTypesMatcher)))),
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
197 unless(hasAncestor(
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
198 cxxMethodDecl(ofClass(equalsBoundNode("container"))))))
150
anatofuz
parents:
diff changeset
199 .bind("BinCmp"),
anatofuz
parents:
diff changeset
200 this);
anatofuz
parents:
diff changeset
201 }
anatofuz
parents:
diff changeset
202
anatofuz
parents:
diff changeset
203 void ContainerSizeEmptyCheck::check(const MatchFinder::MatchResult &Result) {
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
204 const auto *MemberCall = Result.Nodes.getNodeAs<Expr>("SizeCallExpr");
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
205 const auto *MemberCallObject =
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
206 Result.Nodes.getNodeAs<Expr>("MemberCallObject");
150
anatofuz
parents:
diff changeset
207 const auto *BinCmp = Result.Nodes.getNodeAs<CXXOperatorCallExpr>("BinCmp");
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
208 const auto *BinCmpTempl = Result.Nodes.getNodeAs<BinaryOperator>("BinCmp");
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
209 const auto *BinCmpRewritten =
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
210 Result.Nodes.getNodeAs<CXXRewrittenBinaryOperator>("BinCmp");
150
anatofuz
parents:
diff changeset
211 const auto *BinaryOp = Result.Nodes.getNodeAs<BinaryOperator>("SizeBinaryOp");
anatofuz
parents:
diff changeset
212 const auto *Pointee = Result.Nodes.getNodeAs<Expr>("Pointee");
anatofuz
parents:
diff changeset
213 const auto *E =
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
214 MemberCallObject
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
215 ? MemberCallObject
150
anatofuz
parents:
diff changeset
216 : (Pointee ? Pointee : Result.Nodes.getNodeAs<Expr>("STLObject"));
anatofuz
parents:
diff changeset
217 FixItHint Hint;
anatofuz
parents:
diff changeset
218 std::string ReplacementText = std::string(
anatofuz
parents:
diff changeset
219 Lexer::getSourceText(CharSourceRange::getTokenRange(E->getSourceRange()),
anatofuz
parents:
diff changeset
220 *Result.SourceManager, getLangOpts()));
236
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
221 const auto *OpCallExpr = dyn_cast<CXXOperatorCallExpr>(E);
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
222 if (isBinaryOrTernary(E) || isa<UnaryOperator>(E) ||
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
223 (OpCallExpr && (OpCallExpr->getOperator() == OO_Star))) {
150
anatofuz
parents:
diff changeset
224 ReplacementText = "(" + ReplacementText + ")";
anatofuz
parents:
diff changeset
225 }
236
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
226 if (OpCallExpr &&
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
227 OpCallExpr->getOperator() == OverloadedOperatorKind::OO_Arrow) {
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
228 // This can happen if the object is a smart pointer. Don't add anything
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
229 // because a '->' is already there (PR#51776), just call the method.
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
230 ReplacementText += "empty()";
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
231 } else if (E->getType()->isPointerType())
150
anatofuz
parents:
diff changeset
232 ReplacementText += "->empty()";
anatofuz
parents:
diff changeset
233 else
anatofuz
parents:
diff changeset
234 ReplacementText += ".empty()";
anatofuz
parents:
diff changeset
235
anatofuz
parents:
diff changeset
236 if (BinCmp) {
anatofuz
parents:
diff changeset
237 if (BinCmp->getOperator() == OO_ExclaimEqual) {
anatofuz
parents:
diff changeset
238 ReplacementText = "!" + ReplacementText;
anatofuz
parents:
diff changeset
239 }
anatofuz
parents:
diff changeset
240 Hint =
anatofuz
parents:
diff changeset
241 FixItHint::CreateReplacement(BinCmp->getSourceRange(), ReplacementText);
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
242 } else if (BinCmpTempl) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
243 if (BinCmpTempl->getOpcode() == BinaryOperatorKind::BO_NE) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
244 ReplacementText = "!" + ReplacementText;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
245 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
246 Hint = FixItHint::CreateReplacement(BinCmpTempl->getSourceRange(),
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
247 ReplacementText);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
248 } else if (BinCmpRewritten) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
249 if (BinCmpRewritten->getOpcode() == BinaryOperatorKind::BO_NE) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
250 ReplacementText = "!" + ReplacementText;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
251 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
252 Hint = FixItHint::CreateReplacement(BinCmpRewritten->getSourceRange(),
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
253 ReplacementText);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
254 } else if (BinaryOp) { // Determine the correct transformation.
236
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
255 const auto *LiteralLHS =
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
256 llvm::dyn_cast<IntegerLiteral>(BinaryOp->getLHS()->IgnoreImpCasts());
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
257 const auto *LiteralRHS =
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
258 llvm::dyn_cast<IntegerLiteral>(BinaryOp->getRHS()->IgnoreImpCasts());
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
259 const bool ContainerIsLHS = !LiteralLHS;
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
260
150
anatofuz
parents:
diff changeset
261 uint64_t Value = 0;
236
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
262 if (LiteralLHS)
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
263 Value = LiteralLHS->getValue().getLimitedValue();
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
264 else if (LiteralRHS)
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
265 Value = LiteralRHS->getValue().getLimitedValue();
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
266 else
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
267 return;
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
268
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
269 bool Negation = false;
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
270 const auto OpCode = BinaryOp->getOpcode();
150
anatofuz
parents:
diff changeset
271
anatofuz
parents:
diff changeset
272 // Constant that is not handled.
anatofuz
parents:
diff changeset
273 if (Value > 1)
anatofuz
parents:
diff changeset
274 return;
anatofuz
parents:
diff changeset
275
anatofuz
parents:
diff changeset
276 if (Value == 1 && (OpCode == BinaryOperatorKind::BO_EQ ||
anatofuz
parents:
diff changeset
277 OpCode == BinaryOperatorKind::BO_NE))
anatofuz
parents:
diff changeset
278 return;
anatofuz
parents:
diff changeset
279
anatofuz
parents:
diff changeset
280 // Always true, no warnings for that.
anatofuz
parents:
diff changeset
281 if ((OpCode == BinaryOperatorKind::BO_GE && Value == 0 && ContainerIsLHS) ||
anatofuz
parents:
diff changeset
282 (OpCode == BinaryOperatorKind::BO_LE && Value == 0 && !ContainerIsLHS))
anatofuz
parents:
diff changeset
283 return;
anatofuz
parents:
diff changeset
284
anatofuz
parents:
diff changeset
285 // Do not warn for size > 1, 1 < size, size <= 1, 1 >= size.
anatofuz
parents:
diff changeset
286 if (Value == 1) {
anatofuz
parents:
diff changeset
287 if ((OpCode == BinaryOperatorKind::BO_GT && ContainerIsLHS) ||
anatofuz
parents:
diff changeset
288 (OpCode == BinaryOperatorKind::BO_LT && !ContainerIsLHS))
anatofuz
parents:
diff changeset
289 return;
anatofuz
parents:
diff changeset
290 if ((OpCode == BinaryOperatorKind::BO_LE && ContainerIsLHS) ||
anatofuz
parents:
diff changeset
291 (OpCode == BinaryOperatorKind::BO_GE && !ContainerIsLHS))
anatofuz
parents:
diff changeset
292 return;
anatofuz
parents:
diff changeset
293 }
anatofuz
parents:
diff changeset
294
anatofuz
parents:
diff changeset
295 if (OpCode == BinaryOperatorKind::BO_NE && Value == 0)
anatofuz
parents:
diff changeset
296 Negation = true;
anatofuz
parents:
diff changeset
297 if ((OpCode == BinaryOperatorKind::BO_GT ||
anatofuz
parents:
diff changeset
298 OpCode == BinaryOperatorKind::BO_GE) &&
anatofuz
parents:
diff changeset
299 ContainerIsLHS)
anatofuz
parents:
diff changeset
300 Negation = true;
anatofuz
parents:
diff changeset
301 if ((OpCode == BinaryOperatorKind::BO_LT ||
anatofuz
parents:
diff changeset
302 OpCode == BinaryOperatorKind::BO_LE) &&
anatofuz
parents:
diff changeset
303 !ContainerIsLHS)
anatofuz
parents:
diff changeset
304 Negation = true;
anatofuz
parents:
diff changeset
305
anatofuz
parents:
diff changeset
306 if (Negation)
anatofuz
parents:
diff changeset
307 ReplacementText = "!" + ReplacementText;
anatofuz
parents:
diff changeset
308 Hint = FixItHint::CreateReplacement(BinaryOp->getSourceRange(),
anatofuz
parents:
diff changeset
309 ReplacementText);
anatofuz
parents:
diff changeset
310
anatofuz
parents:
diff changeset
311 } else {
anatofuz
parents:
diff changeset
312 // If there is a conversion above the size call to bool, it is safe to just
anatofuz
parents:
diff changeset
313 // replace size with empty.
anatofuz
parents:
diff changeset
314 if (const auto *UnaryOp =
anatofuz
parents:
diff changeset
315 Result.Nodes.getNodeAs<UnaryOperator>("NegOnSize"))
anatofuz
parents:
diff changeset
316 Hint = FixItHint::CreateReplacement(UnaryOp->getSourceRange(),
anatofuz
parents:
diff changeset
317 ReplacementText);
anatofuz
parents:
diff changeset
318 else
anatofuz
parents:
diff changeset
319 Hint = FixItHint::CreateReplacement(MemberCall->getSourceRange(),
anatofuz
parents:
diff changeset
320 "!" + ReplacementText);
anatofuz
parents:
diff changeset
321 }
anatofuz
parents:
diff changeset
322
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
323 auto WarnLoc = MemberCall ? MemberCall->getBeginLoc() : SourceLocation{};
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
324
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
325 if (WarnLoc.isValid()) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
326 diag(WarnLoc, "the 'empty' method should be used to check "
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
327 "for emptiness instead of 'size'")
150
anatofuz
parents:
diff changeset
328 << Hint;
anatofuz
parents:
diff changeset
329 } else {
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
330 WarnLoc = BinCmpTempl
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
331 ? BinCmpTempl->getBeginLoc()
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
332 : (BinCmp ? BinCmp->getBeginLoc()
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
333 : (BinCmpRewritten ? BinCmpRewritten->getBeginLoc()
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
334 : SourceLocation{}));
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
335 diag(WarnLoc, "the 'empty' method should be used to check "
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
336 "for emptiness instead of comparing to an empty object")
150
anatofuz
parents:
diff changeset
337 << Hint;
anatofuz
parents:
diff changeset
338 }
anatofuz
parents:
diff changeset
339
anatofuz
parents:
diff changeset
340 const auto *Container = Result.Nodes.getNodeAs<NamedDecl>("container");
anatofuz
parents:
diff changeset
341 if (const auto *CTS = dyn_cast<ClassTemplateSpecializationDecl>(Container)) {
anatofuz
parents:
diff changeset
342 // The definition of the empty() method is the same for all implicit
anatofuz
parents:
diff changeset
343 // instantiations. In order to avoid duplicate or inconsistent warnings
anatofuz
parents:
diff changeset
344 // (depending on how deduplication is done), we use the same class name
anatofuz
parents:
diff changeset
345 // for all implicit instantiations of a template.
anatofuz
parents:
diff changeset
346 if (CTS->getSpecializationKind() == TSK_ImplicitInstantiation)
anatofuz
parents:
diff changeset
347 Container = CTS->getSpecializedTemplate();
anatofuz
parents:
diff changeset
348 }
anatofuz
parents:
diff changeset
349 const auto *Empty = Result.Nodes.getNodeAs<FunctionDecl>("empty");
anatofuz
parents:
diff changeset
350
anatofuz
parents:
diff changeset
351 diag(Empty->getLocation(), "method %0::empty() defined here",
anatofuz
parents:
diff changeset
352 DiagnosticIDs::Note)
anatofuz
parents:
diff changeset
353 << Container;
anatofuz
parents:
diff changeset
354 }
anatofuz
parents:
diff changeset
355
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
356 } // namespace tidy::readability
150
anatofuz
parents:
diff changeset
357 } // namespace clang