15 #include "../utils/OptionsUtils.h"
16 #include "clang/AST/ASTContext.h"
17 #include "clang/ASTMatchers/ASTMatchFinder.h"
18 #include "llvm/ADT/STLExtras.h"
22 using namespace clang::ast_type_traits;
27 const DynTypedNode &Node) {
29 const auto *AsDecl = Node.get<DeclaratorDecl>();
31 if (AsDecl->getType().isConstQualified())
34 return AsDecl->isImplicit();
37 if (Node.get<EnumConstantDecl>())
40 return llvm::any_of(Result.Context->getParents(Node),
41 [&Result](
const DynTypedNode &
Parent) {
47 const DynTypedNode &Node) {
48 const auto *AsFieldDecl = Node.get<FieldDecl>();
49 if (AsFieldDecl && AsFieldDecl->isBitField())
52 return llvm::any_of(Result.Context->getParents(Node),
53 [&Result](
const DynTypedNode &
Parent) {
59 namespace readability {
66 IgnoreAllFloatingPointValues(
67 Options.get(
"IgnoreAllFloatingPointValues", false)),
68 IgnoreBitFieldsWidths(Options.get(
"IgnoreBitFieldsWidths", true)),
69 IgnorePowersOf2IntegerValues(
70 Options.get(
"IgnorePowersOf2IntegerValues", false)),
71 RawIgnoredIntegerValues(
73 RawIgnoredFloatingPointValues(Options.get(
76 const std::vector<std::string> IgnoredIntegerValuesInput =
78 IgnoredIntegerValues.resize(IgnoredIntegerValuesInput.size());
79 llvm::transform(IgnoredIntegerValuesInput, IgnoredIntegerValues.begin(),
80 [](
const std::string &Value) {
return std::stoll(Value); });
81 llvm::sort(IgnoredIntegerValues);
83 if (!IgnoreAllFloatingPointValues) {
85 const std::vector<std::string> IgnoredFloatingPointValuesInput =
87 IgnoredFloatingPointValues.reserve(IgnoredFloatingPointValuesInput.size());
88 IgnoredDoublePointValues.reserve(IgnoredFloatingPointValuesInput.size());
89 for (
const auto &InputValue : IgnoredFloatingPointValuesInput) {
90 llvm::APFloat FloatValue(llvm::APFloat::IEEEsingle());
92 FloatValue.convertFromString(InputValue, DefaultRoundingMode);
93 assert(StatusOrErr &&
"Invalid floating point representation");
94 consumeError(StatusOrErr.takeError());
95 IgnoredFloatingPointValues.push_back(FloatValue.convertToFloat());
97 llvm::APFloat DoubleValue(llvm::APFloat::IEEEdouble());
99 DoubleValue.convertFromString(InputValue, DefaultRoundingMode);
100 assert(StatusOrErr &&
"Invalid floating point representation");
101 consumeError(StatusOrErr.takeError());
102 IgnoredDoublePointValues.push_back(DoubleValue.convertToDouble());
104 llvm::sort(IgnoredFloatingPointValues.begin(),
105 IgnoredFloatingPointValues.end());
106 llvm::sort(IgnoredDoublePointValues.begin(),
107 IgnoredDoublePointValues.end());
113 IgnoreAllFloatingPointValues);
114 Options.
store(Opts,
"IgnoreBitFieldsWidths", IgnoreBitFieldsWidths);
116 IgnorePowersOf2IntegerValues);
117 Options.
store(Opts,
"IgnoredIntegerValues", RawIgnoredIntegerValues);
119 RawIgnoredFloatingPointValues);
123 Finder->addMatcher(integerLiteral().bind(
"integer"),
this);
124 if (!IgnoreAllFloatingPointValues)
125 Finder->addMatcher(floatLiteral().bind(
"float"),
this);
130 TraversalKindScope RAII(*Result.Context, ast_type_traits::TK_AsIs);
132 checkBoundMatch<IntegerLiteral>(Result,
"integer");
133 checkBoundMatch<FloatingLiteral>(Result,
"float");
136 bool MagicNumbersCheck::isConstant(
const MatchFinder::MatchResult &Result,
137 const Expr &ExprResult)
const {
139 Result.Context->getParents(ExprResult),
140 [&Result](
const DynTypedNode &
Parent) {
146 if (
Parent.get<CStyleCastExpr>() &&
148 Result.Context->getParents(
Parent),
149 [](
const DynTypedNode &GrandParent) {
150 return GrandParent.get<SubstNonTypeTemplateParmExpr>() !=
158 if (
Parent.get<SubstNonTypeTemplateParmExpr>())
163 if (
const auto *UDL =
Parent.get<UserDefinedLiteral>())
164 if (UDL->getLiteralOperatorKind() == UserDefinedLiteral::LOK_String)
171 bool MagicNumbersCheck::isIgnoredValue(
const IntegerLiteral *Literal)
const {
172 const llvm::APInt IntValue = Literal->getValue();
173 const int64_t Value = IntValue.getZExtValue();
177 if (IgnorePowersOf2IntegerValues && IntValue.isPowerOf2())
180 return std::binary_search(IgnoredIntegerValues.begin(),
181 IgnoredIntegerValues.end(), Value);
184 bool MagicNumbersCheck::isIgnoredValue(
const FloatingLiteral *Literal)
const {
185 const llvm::APFloat FloatValue = Literal->getValue();
186 if (FloatValue.isZero())
189 if (&FloatValue.getSemantics() == &llvm::APFloat::IEEEsingle()) {
190 const float Value = FloatValue.convertToFloat();
191 return std::binary_search(IgnoredFloatingPointValues.begin(),
192 IgnoredFloatingPointValues.end(), Value);
195 if (&FloatValue.getSemantics() == &llvm::APFloat::IEEEdouble()) {
196 const double Value = FloatValue.convertToDouble();
197 return std::binary_search(IgnoredDoublePointValues.begin(),
198 IgnoredDoublePointValues.end(), Value);
204 bool MagicNumbersCheck::isSyntheticValue(
const SourceManager *SourceManager,
205 const IntegerLiteral *Literal)
const {
206 const std::pair<FileID, unsigned> FileOffset =
207 SourceManager->getDecomposedLoc(Literal->getLocation());
208 if (FileOffset.first.isInvalid())
211 const StringRef BufferIdentifier =
212 SourceManager->getBuffer(FileOffset.first)->getBufferIdentifier();
214 return BufferIdentifier.empty();
217 bool MagicNumbersCheck::isBitFieldWidth(
218 const clang::ast_matchers::MatchFinder::MatchResult &Result,
219 const IntegerLiteral &Literal)
const {
220 return IgnoreBitFieldsWidths &&
221 llvm::any_of(Result.Context->getParents(Literal),
222 [&Result](
const DynTypedNode &
Parent) {