annotate clang-tools-extra/clang-tidy/modernize/UseDefaultMemberInitCheck.cpp @ 165:597b3f1c2c93

fix call createTailCallEliminationPass
author anatofuz
date Tue, 24 Mar 2020 15:30:52 +0900
parents 1d019706d866
children 0572611fdcc8
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
150
anatofuz
parents:
diff changeset
1 //===--- UseDefaultMemberInitCheck.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
anatofuz
parents:
diff changeset
9 #include "UseDefaultMemberInitCheck.h"
anatofuz
parents:
diff changeset
10 #include "clang/AST/ASTContext.h"
anatofuz
parents:
diff changeset
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
anatofuz
parents:
diff changeset
12 #include "clang/Lex/Lexer.h"
anatofuz
parents:
diff changeset
13
anatofuz
parents:
diff changeset
14 using namespace clang::ast_matchers;
anatofuz
parents:
diff changeset
15
anatofuz
parents:
diff changeset
16 namespace clang {
anatofuz
parents:
diff changeset
17 namespace tidy {
anatofuz
parents:
diff changeset
18 namespace modernize {
anatofuz
parents:
diff changeset
19
anatofuz
parents:
diff changeset
20 static StringRef getValueOfValueInit(const QualType InitType) {
anatofuz
parents:
diff changeset
21 switch (InitType->getScalarTypeKind()) {
anatofuz
parents:
diff changeset
22 case Type::STK_CPointer:
anatofuz
parents:
diff changeset
23 case Type::STK_BlockPointer:
anatofuz
parents:
diff changeset
24 case Type::STK_ObjCObjectPointer:
anatofuz
parents:
diff changeset
25 case Type::STK_MemberPointer:
anatofuz
parents:
diff changeset
26 return "nullptr";
anatofuz
parents:
diff changeset
27
anatofuz
parents:
diff changeset
28 case Type::STK_Bool:
anatofuz
parents:
diff changeset
29 return "false";
anatofuz
parents:
diff changeset
30
anatofuz
parents:
diff changeset
31 case Type::STK_Integral:
anatofuz
parents:
diff changeset
32 switch (InitType->castAs<BuiltinType>()->getKind()) {
anatofuz
parents:
diff changeset
33 case BuiltinType::Char_U:
anatofuz
parents:
diff changeset
34 case BuiltinType::UChar:
anatofuz
parents:
diff changeset
35 case BuiltinType::Char_S:
anatofuz
parents:
diff changeset
36 case BuiltinType::SChar:
anatofuz
parents:
diff changeset
37 return "'\\0'";
anatofuz
parents:
diff changeset
38 case BuiltinType::WChar_U:
anatofuz
parents:
diff changeset
39 case BuiltinType::WChar_S:
anatofuz
parents:
diff changeset
40 return "L'\\0'";
anatofuz
parents:
diff changeset
41 case BuiltinType::Char16:
anatofuz
parents:
diff changeset
42 return "u'\\0'";
anatofuz
parents:
diff changeset
43 case BuiltinType::Char32:
anatofuz
parents:
diff changeset
44 return "U'\\0'";
anatofuz
parents:
diff changeset
45 default:
anatofuz
parents:
diff changeset
46 return "0";
anatofuz
parents:
diff changeset
47 }
anatofuz
parents:
diff changeset
48
anatofuz
parents:
diff changeset
49 case Type::STK_Floating:
anatofuz
parents:
diff changeset
50 switch (InitType->castAs<BuiltinType>()->getKind()) {
anatofuz
parents:
diff changeset
51 case BuiltinType::Half:
anatofuz
parents:
diff changeset
52 case BuiltinType::Float:
anatofuz
parents:
diff changeset
53 return "0.0f";
anatofuz
parents:
diff changeset
54 default:
anatofuz
parents:
diff changeset
55 return "0.0";
anatofuz
parents:
diff changeset
56 }
anatofuz
parents:
diff changeset
57
anatofuz
parents:
diff changeset
58 case Type::STK_FloatingComplex:
anatofuz
parents:
diff changeset
59 case Type::STK_IntegralComplex:
anatofuz
parents:
diff changeset
60 return getValueOfValueInit(
anatofuz
parents:
diff changeset
61 InitType->castAs<ComplexType>()->getElementType());
anatofuz
parents:
diff changeset
62
anatofuz
parents:
diff changeset
63 case Type::STK_FixedPoint:
anatofuz
parents:
diff changeset
64 switch (InitType->castAs<BuiltinType>()->getKind()) {
anatofuz
parents:
diff changeset
65 case BuiltinType::ShortAccum:
anatofuz
parents:
diff changeset
66 case BuiltinType::SatShortAccum:
anatofuz
parents:
diff changeset
67 return "0.0hk";
anatofuz
parents:
diff changeset
68 case BuiltinType::Accum:
anatofuz
parents:
diff changeset
69 case BuiltinType::SatAccum:
anatofuz
parents:
diff changeset
70 return "0.0k";
anatofuz
parents:
diff changeset
71 case BuiltinType::LongAccum:
anatofuz
parents:
diff changeset
72 case BuiltinType::SatLongAccum:
anatofuz
parents:
diff changeset
73 return "0.0lk";
anatofuz
parents:
diff changeset
74 case BuiltinType::UShortAccum:
anatofuz
parents:
diff changeset
75 case BuiltinType::SatUShortAccum:
anatofuz
parents:
diff changeset
76 return "0.0uhk";
anatofuz
parents:
diff changeset
77 case BuiltinType::UAccum:
anatofuz
parents:
diff changeset
78 case BuiltinType::SatUAccum:
anatofuz
parents:
diff changeset
79 return "0.0uk";
anatofuz
parents:
diff changeset
80 case BuiltinType::ULongAccum:
anatofuz
parents:
diff changeset
81 case BuiltinType::SatULongAccum:
anatofuz
parents:
diff changeset
82 return "0.0ulk";
anatofuz
parents:
diff changeset
83 case BuiltinType::ShortFract:
anatofuz
parents:
diff changeset
84 case BuiltinType::SatShortFract:
anatofuz
parents:
diff changeset
85 return "0.0hr";
anatofuz
parents:
diff changeset
86 case BuiltinType::Fract:
anatofuz
parents:
diff changeset
87 case BuiltinType::SatFract:
anatofuz
parents:
diff changeset
88 return "0.0r";
anatofuz
parents:
diff changeset
89 case BuiltinType::LongFract:
anatofuz
parents:
diff changeset
90 case BuiltinType::SatLongFract:
anatofuz
parents:
diff changeset
91 return "0.0lr";
anatofuz
parents:
diff changeset
92 case BuiltinType::UShortFract:
anatofuz
parents:
diff changeset
93 case BuiltinType::SatUShortFract:
anatofuz
parents:
diff changeset
94 return "0.0uhr";
anatofuz
parents:
diff changeset
95 case BuiltinType::UFract:
anatofuz
parents:
diff changeset
96 case BuiltinType::SatUFract:
anatofuz
parents:
diff changeset
97 return "0.0ur";
anatofuz
parents:
diff changeset
98 case BuiltinType::ULongFract:
anatofuz
parents:
diff changeset
99 case BuiltinType::SatULongFract:
anatofuz
parents:
diff changeset
100 return "0.0ulr";
anatofuz
parents:
diff changeset
101 default:
anatofuz
parents:
diff changeset
102 llvm_unreachable("Unhandled fixed point BuiltinType");
anatofuz
parents:
diff changeset
103 }
anatofuz
parents:
diff changeset
104 }
anatofuz
parents:
diff changeset
105 llvm_unreachable("Invalid scalar type kind");
anatofuz
parents:
diff changeset
106 }
anatofuz
parents:
diff changeset
107
anatofuz
parents:
diff changeset
108 static bool isZero(const Expr *E) {
anatofuz
parents:
diff changeset
109 switch (E->getStmtClass()) {
anatofuz
parents:
diff changeset
110 case Stmt::CXXNullPtrLiteralExprClass:
anatofuz
parents:
diff changeset
111 case Stmt::ImplicitValueInitExprClass:
anatofuz
parents:
diff changeset
112 return true;
anatofuz
parents:
diff changeset
113 case Stmt::InitListExprClass:
anatofuz
parents:
diff changeset
114 return cast<InitListExpr>(E)->getNumInits() == 0;
anatofuz
parents:
diff changeset
115 case Stmt::CharacterLiteralClass:
anatofuz
parents:
diff changeset
116 return !cast<CharacterLiteral>(E)->getValue();
anatofuz
parents:
diff changeset
117 case Stmt::CXXBoolLiteralExprClass:
anatofuz
parents:
diff changeset
118 return !cast<CXXBoolLiteralExpr>(E)->getValue();
anatofuz
parents:
diff changeset
119 case Stmt::IntegerLiteralClass:
anatofuz
parents:
diff changeset
120 return !cast<IntegerLiteral>(E)->getValue();
anatofuz
parents:
diff changeset
121 case Stmt::FloatingLiteralClass: {
anatofuz
parents:
diff changeset
122 llvm::APFloat Value = cast<FloatingLiteral>(E)->getValue();
anatofuz
parents:
diff changeset
123 return Value.isZero() && !Value.isNegative();
anatofuz
parents:
diff changeset
124 }
anatofuz
parents:
diff changeset
125 default:
anatofuz
parents:
diff changeset
126 return false;
anatofuz
parents:
diff changeset
127 }
anatofuz
parents:
diff changeset
128 }
anatofuz
parents:
diff changeset
129
anatofuz
parents:
diff changeset
130 static const Expr *ignoreUnaryPlus(const Expr *E) {
anatofuz
parents:
diff changeset
131 auto *UnaryOp = dyn_cast<UnaryOperator>(E);
anatofuz
parents:
diff changeset
132 if (UnaryOp && UnaryOp->getOpcode() == UO_Plus)
anatofuz
parents:
diff changeset
133 return UnaryOp->getSubExpr();
anatofuz
parents:
diff changeset
134 return E;
anatofuz
parents:
diff changeset
135 }
anatofuz
parents:
diff changeset
136
anatofuz
parents:
diff changeset
137 static const Expr *getInitializer(const Expr *E) {
anatofuz
parents:
diff changeset
138 auto *InitList = dyn_cast<InitListExpr>(E);
anatofuz
parents:
diff changeset
139 if (InitList && InitList->getNumInits() == 1)
anatofuz
parents:
diff changeset
140 return InitList->getInit(0)->IgnoreParenImpCasts();
anatofuz
parents:
diff changeset
141 return E;
anatofuz
parents:
diff changeset
142 }
anatofuz
parents:
diff changeset
143
anatofuz
parents:
diff changeset
144 static bool sameValue(const Expr *E1, const Expr *E2) {
anatofuz
parents:
diff changeset
145 E1 = ignoreUnaryPlus(getInitializer(E1->IgnoreParenImpCasts()));
anatofuz
parents:
diff changeset
146 E2 = ignoreUnaryPlus(getInitializer(E2->IgnoreParenImpCasts()));
anatofuz
parents:
diff changeset
147
anatofuz
parents:
diff changeset
148 if (isZero(E1) && isZero(E2))
anatofuz
parents:
diff changeset
149 return true;
anatofuz
parents:
diff changeset
150
anatofuz
parents:
diff changeset
151 if (E1->getStmtClass() != E2->getStmtClass())
anatofuz
parents:
diff changeset
152 return false;
anatofuz
parents:
diff changeset
153
anatofuz
parents:
diff changeset
154 switch (E1->getStmtClass()) {
anatofuz
parents:
diff changeset
155 case Stmt::UnaryOperatorClass:
anatofuz
parents:
diff changeset
156 return sameValue(cast<UnaryOperator>(E1)->getSubExpr(),
anatofuz
parents:
diff changeset
157 cast<UnaryOperator>(E2)->getSubExpr());
anatofuz
parents:
diff changeset
158 case Stmt::CharacterLiteralClass:
anatofuz
parents:
diff changeset
159 return cast<CharacterLiteral>(E1)->getValue() ==
anatofuz
parents:
diff changeset
160 cast<CharacterLiteral>(E2)->getValue();
anatofuz
parents:
diff changeset
161 case Stmt::CXXBoolLiteralExprClass:
anatofuz
parents:
diff changeset
162 return cast<CXXBoolLiteralExpr>(E1)->getValue() ==
anatofuz
parents:
diff changeset
163 cast<CXXBoolLiteralExpr>(E2)->getValue();
anatofuz
parents:
diff changeset
164 case Stmt::IntegerLiteralClass:
anatofuz
parents:
diff changeset
165 return cast<IntegerLiteral>(E1)->getValue() ==
anatofuz
parents:
diff changeset
166 cast<IntegerLiteral>(E2)->getValue();
anatofuz
parents:
diff changeset
167 case Stmt::FloatingLiteralClass:
anatofuz
parents:
diff changeset
168 return cast<FloatingLiteral>(E1)->getValue().bitwiseIsEqual(
anatofuz
parents:
diff changeset
169 cast<FloatingLiteral>(E2)->getValue());
anatofuz
parents:
diff changeset
170 case Stmt::StringLiteralClass:
anatofuz
parents:
diff changeset
171 return cast<StringLiteral>(E1)->getString() ==
anatofuz
parents:
diff changeset
172 cast<StringLiteral>(E2)->getString();
anatofuz
parents:
diff changeset
173 case Stmt::DeclRefExprClass:
anatofuz
parents:
diff changeset
174 return cast<DeclRefExpr>(E1)->getDecl() == cast<DeclRefExpr>(E2)->getDecl();
anatofuz
parents:
diff changeset
175 default:
anatofuz
parents:
diff changeset
176 return false;
anatofuz
parents:
diff changeset
177 }
anatofuz
parents:
diff changeset
178 }
anatofuz
parents:
diff changeset
179
anatofuz
parents:
diff changeset
180 UseDefaultMemberInitCheck::UseDefaultMemberInitCheck(StringRef Name,
anatofuz
parents:
diff changeset
181 ClangTidyContext *Context)
anatofuz
parents:
diff changeset
182 : ClangTidyCheck(Name, Context),
anatofuz
parents:
diff changeset
183 UseAssignment(Options.get("UseAssignment", 0) != 0),
anatofuz
parents:
diff changeset
184 IgnoreMacros(Options.getLocalOrGlobal("IgnoreMacros", true) != 0) {}
anatofuz
parents:
diff changeset
185
anatofuz
parents:
diff changeset
186 void UseDefaultMemberInitCheck::storeOptions(
anatofuz
parents:
diff changeset
187 ClangTidyOptions::OptionMap &Opts) {
anatofuz
parents:
diff changeset
188 Options.store(Opts, "UseAssignment", UseAssignment);
anatofuz
parents:
diff changeset
189 Options.store(Opts, "IgnoreMacros", IgnoreMacros);
anatofuz
parents:
diff changeset
190 }
anatofuz
parents:
diff changeset
191
anatofuz
parents:
diff changeset
192 void UseDefaultMemberInitCheck::registerMatchers(MatchFinder *Finder) {
anatofuz
parents:
diff changeset
193 if (!getLangOpts().CPlusPlus11)
anatofuz
parents:
diff changeset
194 return;
anatofuz
parents:
diff changeset
195
anatofuz
parents:
diff changeset
196 auto Init =
anatofuz
parents:
diff changeset
197 anyOf(stringLiteral(), characterLiteral(), integerLiteral(),
anatofuz
parents:
diff changeset
198 unaryOperator(anyOf(hasOperatorName("+"), hasOperatorName("-")),
anatofuz
parents:
diff changeset
199 hasUnaryOperand(integerLiteral())),
anatofuz
parents:
diff changeset
200 floatLiteral(),
anatofuz
parents:
diff changeset
201 unaryOperator(anyOf(hasOperatorName("+"), hasOperatorName("-")),
anatofuz
parents:
diff changeset
202 hasUnaryOperand(floatLiteral())),
anatofuz
parents:
diff changeset
203 cxxBoolLiteral(), cxxNullPtrLiteralExpr(), implicitValueInitExpr(),
anatofuz
parents:
diff changeset
204 initListExpr(), declRefExpr(to(enumConstantDecl())));
anatofuz
parents:
diff changeset
205
anatofuz
parents:
diff changeset
206 Finder->addMatcher(
anatofuz
parents:
diff changeset
207 cxxConstructorDecl(
anatofuz
parents:
diff changeset
208 isDefaultConstructor(), unless(isInstantiated()),
anatofuz
parents:
diff changeset
209 forEachConstructorInitializer(
anatofuz
parents:
diff changeset
210 cxxCtorInitializer(
anatofuz
parents:
diff changeset
211 forField(unless(anyOf(getLangOpts().CPlusPlus2a
anatofuz
parents:
diff changeset
212 ? unless(anything())
anatofuz
parents:
diff changeset
213 : isBitField(),
anatofuz
parents:
diff changeset
214 hasInClassInitializer(anything()),
anatofuz
parents:
diff changeset
215 hasParent(recordDecl(isUnion()))))),
anatofuz
parents:
diff changeset
216 isWritten(), withInitializer(ignoringImplicit(Init)))
anatofuz
parents:
diff changeset
217 .bind("default"))),
anatofuz
parents:
diff changeset
218 this);
anatofuz
parents:
diff changeset
219
anatofuz
parents:
diff changeset
220 Finder->addMatcher(
anatofuz
parents:
diff changeset
221 cxxConstructorDecl(
anatofuz
parents:
diff changeset
222 unless(ast_matchers::isTemplateInstantiation()),
anatofuz
parents:
diff changeset
223 forEachConstructorInitializer(
anatofuz
parents:
diff changeset
224 cxxCtorInitializer(forField(hasInClassInitializer(anything())),
anatofuz
parents:
diff changeset
225 isWritten(),
anatofuz
parents:
diff changeset
226 withInitializer(ignoringImplicit(Init)))
anatofuz
parents:
diff changeset
227 .bind("existing"))),
anatofuz
parents:
diff changeset
228 this);
anatofuz
parents:
diff changeset
229 }
anatofuz
parents:
diff changeset
230
anatofuz
parents:
diff changeset
231 void UseDefaultMemberInitCheck::check(const MatchFinder::MatchResult &Result) {
anatofuz
parents:
diff changeset
232 if (const auto *Default =
anatofuz
parents:
diff changeset
233 Result.Nodes.getNodeAs<CXXCtorInitializer>("default"))
anatofuz
parents:
diff changeset
234 checkDefaultInit(Result, Default);
anatofuz
parents:
diff changeset
235 else if (const auto *Existing =
anatofuz
parents:
diff changeset
236 Result.Nodes.getNodeAs<CXXCtorInitializer>("existing"))
anatofuz
parents:
diff changeset
237 checkExistingInit(Result, Existing);
anatofuz
parents:
diff changeset
238 else
anatofuz
parents:
diff changeset
239 llvm_unreachable("Bad Callback. No node provided.");
anatofuz
parents:
diff changeset
240 }
anatofuz
parents:
diff changeset
241
anatofuz
parents:
diff changeset
242 void UseDefaultMemberInitCheck::checkDefaultInit(
anatofuz
parents:
diff changeset
243 const MatchFinder::MatchResult &Result, const CXXCtorInitializer *Init) {
anatofuz
parents:
diff changeset
244 const FieldDecl *Field = Init->getAnyMember();
anatofuz
parents:
diff changeset
245
anatofuz
parents:
diff changeset
246 SourceLocation StartLoc = Field->getBeginLoc();
anatofuz
parents:
diff changeset
247 if (StartLoc.isMacroID() && IgnoreMacros)
anatofuz
parents:
diff changeset
248 return;
anatofuz
parents:
diff changeset
249
anatofuz
parents:
diff changeset
250 SourceLocation FieldEnd =
anatofuz
parents:
diff changeset
251 Lexer::getLocForEndOfToken(Field->getSourceRange().getEnd(), 0,
anatofuz
parents:
diff changeset
252 *Result.SourceManager, getLangOpts());
anatofuz
parents:
diff changeset
253 SourceLocation LParenEnd = Lexer::getLocForEndOfToken(
anatofuz
parents:
diff changeset
254 Init->getLParenLoc(), 0, *Result.SourceManager, getLangOpts());
anatofuz
parents:
diff changeset
255 CharSourceRange InitRange =
anatofuz
parents:
diff changeset
256 CharSourceRange::getCharRange(LParenEnd, Init->getRParenLoc());
anatofuz
parents:
diff changeset
257
anatofuz
parents:
diff changeset
258 bool ValueInit = isa<ImplicitValueInitExpr>(Init->getInit());
anatofuz
parents:
diff changeset
259 bool CanAssign = UseAssignment && (!ValueInit || !Init->getInit()->getType()->isEnumeralType());
anatofuz
parents:
diff changeset
260
anatofuz
parents:
diff changeset
261 auto Diag =
anatofuz
parents:
diff changeset
262 diag(Field->getLocation(), "use default member initializer for %0")
anatofuz
parents:
diff changeset
263 << Field
anatofuz
parents:
diff changeset
264 << FixItHint::CreateInsertion(FieldEnd, CanAssign ? " = " : "{")
anatofuz
parents:
diff changeset
265 << FixItHint::CreateInsertionFromRange(FieldEnd, InitRange);
anatofuz
parents:
diff changeset
266
anatofuz
parents:
diff changeset
267 if (CanAssign && ValueInit)
anatofuz
parents:
diff changeset
268 Diag << FixItHint::CreateInsertion(
anatofuz
parents:
diff changeset
269 FieldEnd, getValueOfValueInit(Init->getInit()->getType()));
anatofuz
parents:
diff changeset
270
anatofuz
parents:
diff changeset
271 if (!CanAssign)
anatofuz
parents:
diff changeset
272 Diag << FixItHint::CreateInsertion(FieldEnd, "}");
anatofuz
parents:
diff changeset
273
anatofuz
parents:
diff changeset
274 Diag << FixItHint::CreateRemoval(Init->getSourceRange());
anatofuz
parents:
diff changeset
275 }
anatofuz
parents:
diff changeset
276
anatofuz
parents:
diff changeset
277 void UseDefaultMemberInitCheck::checkExistingInit(
anatofuz
parents:
diff changeset
278 const MatchFinder::MatchResult &Result, const CXXCtorInitializer *Init) {
anatofuz
parents:
diff changeset
279 const FieldDecl *Field = Init->getAnyMember();
anatofuz
parents:
diff changeset
280
anatofuz
parents:
diff changeset
281 if (!sameValue(Field->getInClassInitializer(), Init->getInit()))
anatofuz
parents:
diff changeset
282 return;
anatofuz
parents:
diff changeset
283
anatofuz
parents:
diff changeset
284 diag(Init->getSourceLocation(), "member initializer for %0 is redundant")
anatofuz
parents:
diff changeset
285 << Field
anatofuz
parents:
diff changeset
286 << FixItHint::CreateRemoval(Init->getSourceRange());
anatofuz
parents:
diff changeset
287 }
anatofuz
parents:
diff changeset
288
anatofuz
parents:
diff changeset
289 } // namespace modernize
anatofuz
parents:
diff changeset
290 } // namespace tidy
anatofuz
parents:
diff changeset
291 } // namespace clang