|
8 | 8 |
|
9 | 9 | #include "UseDefaultMemberInitCheck.h"
|
10 | 10 | #include "clang/AST/ASTContext.h"
|
| 11 | +#include "clang/AST/Expr.h" |
11 | 12 | #include "clang/ASTMatchers/ASTMatchFinder.h"
|
| 13 | +#include "clang/ASTMatchers/ASTMatchers.h" |
12 | 14 | #include "clang/Lex/Lexer.h"
|
| 15 | +#include "llvm/ADT/TypeSwitch.h" |
13 | 16 |
|
14 | 17 | using namespace clang::ast_matchers;
|
15 | 18 |
|
16 | 19 | namespace clang::tidy::modernize {
|
17 | 20 |
|
| 21 | +static bool isExprAllowedInMemberInit(const Expr *E) { |
| 22 | + if (!E) |
| 23 | + return false; |
| 24 | + return llvm::TypeSwitch<const Expr *, bool>(E) |
| 25 | + .Case<IntegerLiteral, FloatingLiteral, CXXBoolLiteralExpr, |
| 26 | + CXXNullPtrLiteralExpr, CharacterLiteral, StringLiteral>( |
| 27 | + [](const auto *) { return true; }) |
| 28 | + .Case<ImplicitValueInitExpr>([](const auto *) { return true; }) |
| 29 | + .Case<ParenExpr>([](const ParenExpr *PE) { |
| 30 | + return isExprAllowedInMemberInit(PE->getSubExpr()); |
| 31 | + }) |
| 32 | + .Case<UnaryOperator>([](const UnaryOperator *UO) { |
| 33 | + return isExprAllowedInMemberInit(UO->getSubExpr()); |
| 34 | + }) |
| 35 | + .Case<BinaryOperator>([](const BinaryOperator *BO) { |
| 36 | + return isExprAllowedInMemberInit(BO->getLHS()) && |
| 37 | + isExprAllowedInMemberInit(BO->getRHS()); |
| 38 | + }) |
| 39 | + .Case<CastExpr>([](const CastExpr *CE) { |
| 40 | + return isExprAllowedInMemberInit(CE->getSubExpr()); |
| 41 | + }) |
| 42 | + .Case<DeclRefExpr>([](const DeclRefExpr *DRE) { |
| 43 | + if (const ValueDecl *D = DRE->getDecl()) { |
| 44 | + if (isa<EnumConstantDecl>(D)) |
| 45 | + return true; |
| 46 | + if (const auto *VD = dyn_cast<VarDecl>(D)) |
| 47 | + return VD->isConstexpr() || VD->getStorageClass() == SC_Static; |
| 48 | + } |
| 49 | + return false; |
| 50 | + }) |
| 51 | + .Default(false); |
| 52 | +} |
| 53 | + |
18 | 54 | namespace {
|
| 55 | + |
19 | 56 | AST_MATCHER_P(InitListExpr, initCountIs, unsigned, N) {
|
20 | 57 | return Node.getNumInits() == N;
|
21 | 58 | }
|
| 59 | + |
| 60 | +AST_MATCHER(Expr, allowedInitExpr) { return isExprAllowedInMemberInit(&Node); } |
| 61 | + |
22 | 62 | } // namespace
|
23 | 63 |
|
24 | 64 | static StringRef getValueOfValueInit(const QualType InitType) {
|
@@ -206,30 +246,10 @@ void UseDefaultMemberInitCheck::storeOptions(
|
206 | 246 | }
|
207 | 247 |
|
208 | 248 | void UseDefaultMemberInitCheck::registerMatchers(MatchFinder *Finder) {
|
209 |
| - auto NumericLiteral = anyOf(integerLiteral(), floatLiteral()); |
210 |
| - auto UnaryNumericLiteral = unaryOperator(hasAnyOperatorName("+", "-"), |
211 |
| - hasUnaryOperand(NumericLiteral)); |
212 |
| - |
213 |
| - auto ConstExprRef = varDecl(anyOf(isConstexpr(), isStaticStorageClass())); |
214 |
| - auto ImmutableRef = |
215 |
| - declRefExpr(to(decl(anyOf(enumConstantDecl(), ConstExprRef)))); |
216 |
| - |
217 |
| - auto BinaryNumericExpr = binaryOperator( |
218 |
| - hasOperands(anyOf(NumericLiteral, ImmutableRef, binaryOperator()), |
219 |
| - anyOf(NumericLiteral, ImmutableRef, binaryOperator()))); |
220 |
| - |
221 |
| - auto InitBase = |
222 |
| - anyOf(stringLiteral(), characterLiteral(), NumericLiteral, |
223 |
| - UnaryNumericLiteral, cxxBoolLiteral(), cxxNullPtrLiteralExpr(), |
224 |
| - implicitValueInitExpr(), ImmutableRef, BinaryNumericExpr); |
225 |
| - |
226 |
| - auto ExplicitCastExpr = castExpr(hasSourceExpression(InitBase)); |
227 |
| - auto InitMatcher = anyOf(InitBase, ExplicitCastExpr); |
228 |
| - |
229 |
| - auto Init = |
230 |
| - anyOf(initListExpr(anyOf(allOf(initCountIs(1), hasInit(0, InitMatcher)), |
231 |
| - initCountIs(0), hasType(arrayType()))), |
232 |
| - InitBase, ExplicitCastExpr); |
| 249 | + auto Init = anyOf( |
| 250 | + initListExpr(anyOf(allOf(initCountIs(1), hasInit(0, allowedInitExpr())), |
| 251 | + initCountIs(0), hasType(arrayType()))), |
| 252 | + allowedInitExpr()); |
233 | 253 |
|
234 | 254 | Finder->addMatcher(
|
235 | 255 | cxxConstructorDecl(forEachConstructorInitializer(
|
|
0 commit comments