15#include "../utils/OptionsUtils.h"
16#include "clang/AST/ASTContext.h"
17#include "clang/AST/ASTTypeTraits.h"
18#include "clang/AST/Type.h"
19#include "clang/ASTMatchers/ASTMatchFinder.h"
20#include "llvm/ADT/STLExtras.h"
28 const DynTypedNode &Node) {
30 const auto *AsDecl =
Node.get<DeclaratorDecl>();
32 if (AsDecl->getType().isConstQualified())
35 return AsDecl->isImplicit();
38 if (
Node.get<EnumConstantDecl>())
41 return llvm::any_of(Result.Context->getParents(
Node),
42 [&Result](
const DynTypedNode &
Parent) {
43 return isUsedToInitializeAConstant(Result, Parent);
48 const DynTypedNode &Node) {
50 if (
Node.get<TypeAliasDecl>() ||
Node.get<TypedefNameDecl>())
53 return llvm::any_of(Result.Context->getParents(
Node),
54 [&Result](
const DynTypedNode &
Parent) {
55 return isUsedToDefineATypeAlias(Result, Parent);
60 const DynTypedNode &Node) {
61 const auto *AsFieldDecl =
Node.get<FieldDecl>();
62 if (AsFieldDecl && AsFieldDecl->isBitField())
65 return llvm::any_of(Result.Context->getParents(
Node),
66 [&Result](
const DynTypedNode &
Parent) {
67 return isUsedToDefineABitField(Result, Parent);
71namespace tidy::readability {
78 IgnoreAllFloatingPointValues(
79 Options.get(
"IgnoreAllFloatingPointValues", false)),
80 IgnoreBitFieldsWidths(Options.get(
"IgnoreBitFieldsWidths", true)),
81 IgnorePowersOf2IntegerValues(
82 Options.get(
"IgnorePowersOf2IntegerValues", false)),
83 IgnoreTypeAliases(Options.get(
"IgnoreTypeAliases", false)),
84 IgnoreUserDefinedLiterals(
85 Options.get(
"IgnoreUserDefinedLiterals", false)),
86 RawIgnoredIntegerValues(
88 RawIgnoredFloatingPointValues(Options.get(
91 const std::vector<StringRef> IgnoredIntegerValuesInput =
93 IgnoredIntegerValues.resize(IgnoredIntegerValuesInput.size());
94 llvm::transform(IgnoredIntegerValuesInput, IgnoredIntegerValues.begin(),
97 Value.getAsInteger(10, Res);
100 llvm::sort(IgnoredIntegerValues);
102 if (!IgnoreAllFloatingPointValues) {
104 const std::vector<StringRef> IgnoredFloatingPointValuesInput =
106 IgnoredFloatingPointValues.reserve(IgnoredFloatingPointValuesInput.size());
107 IgnoredDoublePointValues.reserve(IgnoredFloatingPointValuesInput.size());
108 for (
const auto &InputValue : IgnoredFloatingPointValuesInput) {
109 llvm::APFloat FloatValue(llvm::APFloat::IEEEsingle());
111 FloatValue.convertFromString(InputValue, DefaultRoundingMode);
112 assert(StatusOrErr &&
"Invalid floating point representation");
113 consumeError(StatusOrErr.takeError());
114 IgnoredFloatingPointValues.push_back(FloatValue.convertToFloat());
116 llvm::APFloat DoubleValue(llvm::APFloat::IEEEdouble());
118 DoubleValue.convertFromString(InputValue, DefaultRoundingMode);
119 assert(StatusOrErr &&
"Invalid floating point representation");
120 consumeError(StatusOrErr.takeError());
121 IgnoredDoublePointValues.push_back(DoubleValue.convertToDouble());
123 llvm::sort(IgnoredFloatingPointValues);
124 llvm::sort(IgnoredDoublePointValues);
130 IgnoreAllFloatingPointValues);
131 Options.
store(Opts,
"IgnoreBitFieldsWidths", IgnoreBitFieldsWidths);
133 IgnorePowersOf2IntegerValues);
134 Options.
store(Opts,
"IgnoreTypeAliases", IgnoreTypeAliases);
135 Options.
store(Opts,
"IgnoreUserDefinedLiterals", IgnoreUserDefinedLiterals);
136 Options.
store(Opts,
"IgnoredIntegerValues", RawIgnoredIntegerValues);
138 RawIgnoredFloatingPointValues);
142 Finder->addMatcher(integerLiteral().bind(
"integer"),
this);
143 if (!IgnoreAllFloatingPointValues)
144 Finder->addMatcher(floatLiteral().bind(
"float"),
this);
149 TraversalKindScope RAII(*Result.Context, TK_AsIs);
151 checkBoundMatch<IntegerLiteral>(Result,
"integer");
152 checkBoundMatch<FloatingLiteral>(Result,
"float");
155bool MagicNumbersCheck::isConstant(
const MatchFinder::MatchResult &Result,
156 const Expr &ExprResult)
const {
158 Result.Context->getParents(ExprResult),
159 [
this, &Result](
const DynTypedNode &
Parent) {
160 if (isUsedToInitializeAConstant(Result, Parent))
163 if (IgnoreTypeAliases && isUsedToDefineATypeAlias(Result, Parent))
168 if (Parent.get<CStyleCastExpr>() &&
170 Result.Context->getParents(Parent),
171 [](const DynTypedNode &GrandParent) {
172 return GrandParent.get<SubstNonTypeTemplateParmExpr>() !=
180 if (
Parent.get<SubstNonTypeTemplateParmExpr>())
185 if (
const auto *UDL =
Parent.get<UserDefinedLiteral>())
186 if (UDL->getLiteralOperatorKind() == UserDefinedLiteral::LOK_String)
193bool MagicNumbersCheck::isIgnoredValue(
const IntegerLiteral *Literal)
const {
194 if (Literal->getType()->isBitIntType()) {
197 const llvm::APInt IntValue = Literal->getValue();
198 const int64_t Value = IntValue.getZExtValue();
202 if (IgnorePowersOf2IntegerValues && IntValue.isPowerOf2())
205 return std::binary_search(IgnoredIntegerValues.begin(),
206 IgnoredIntegerValues.end(), Value);
209bool MagicNumbersCheck::isIgnoredValue(
const FloatingLiteral *Literal)
const {
210 const llvm::APFloat FloatValue = Literal->getValue();
211 if (FloatValue.isZero())
214 if (&FloatValue.getSemantics() == &llvm::APFloat::IEEEsingle()) {
215 const float Value = FloatValue.convertToFloat();
216 return std::binary_search(IgnoredFloatingPointValues.begin(),
217 IgnoredFloatingPointValues.end(), Value);
220 if (&FloatValue.getSemantics() == &llvm::APFloat::IEEEdouble()) {
221 const double Value = FloatValue.convertToDouble();
222 return std::binary_search(IgnoredDoublePointValues.begin(),
223 IgnoredDoublePointValues.end(), Value);
229bool MagicNumbersCheck::isSyntheticValue(
const SourceManager *SourceManager,
230 const IntegerLiteral *Literal)
const {
231 const std::pair<FileID, unsigned> FileOffset =
232 SourceManager->getDecomposedLoc(Literal->getLocation());
233 if (FileOffset.first.isInvalid())
236 const StringRef BufferIdentifier =
237 SourceManager->getBufferOrFake(FileOffset.first).getBufferIdentifier();
239 return BufferIdentifier.empty();
242bool MagicNumbersCheck::isBitFieldWidth(
243 const clang::ast_matchers::MatchFinder::MatchResult &Result,
244 const IntegerLiteral &Literal)
const {
245 return IgnoreBitFieldsWidths &&
246 llvm::any_of(Result.Context->getParents(Literal),
247 [&Result](
const DynTypedNode &
Parent) {
248 return isUsedToDefineABitField(Result, Parent);
252bool MagicNumbersCheck::isUserDefinedLiteral(
253 const clang::ast_matchers::MatchFinder::MatchResult &Result,
254 const clang::Expr &Literal)
const {
255 DynTypedNodeList
Parents = Result.Context->getParents(Literal);
258 return Parents[0].get<UserDefinedLiteral>() !=
nullptr;
llvm::SmallString< 256U > Name
::clang::DynTypedNode Node
void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, StringRef Value) const
Stores an option with the check-local name LocalName with string value Value to Options.
Base class for all clang-tidy checks.
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
void storeOptions(ClangTidyOptions::OptionMap &Opts) override
Should store all options supported by this check with their current values or default values for opti...
MagicNumbersCheck(StringRef Name, ClangTidyContext *Context)
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
ClangTidyChecks that register ASTMatchers should do the actual work in here.
void registerMatchers(ast_matchers::MatchFinder *Finder) override
Override this to register AST matchers with Finder.
const char DefaultIgnoredIntegerValues[]
const char DefaultIgnoredFloatingPointValues[]
std::vector< StringRef > parseStringList(StringRef Option)
Parse a semicolon separated list of strings.
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
static bool isUsedToDefineATypeAlias(const MatchFinder::MatchResult &Result, const DynTypedNode &Node)
static bool isUsedToDefineABitField(const MatchFinder::MatchResult &Result, const DynTypedNode &Node)
static bool isUsedToInitializeAConstant(const MatchFinder::MatchResult &Result, const DynTypedNode &Node)
llvm::StringMap< ClangTidyValue > OptionMap