11 #include "clang/AST/ASTContext.h" 12 #include "clang/ASTMatchers/ASTMatchFinder.h" 20 static constexpr llvm::StringLiteral
LoopName =
21 llvm::StringLiteral(
"forLoopName");
23 llvm::StringLiteral(
"loopVar");
25 llvm::StringLiteral(
"loopVarCast");
27 llvm::StringLiteral(
"loopUpperBound");
29 llvm::StringLiteral(
"loopIncrement");
44 void TooSmallLoopVariableCheck::registerMatchers(MatchFinder *Finder) {
45 StatementMatcher LoopVarMatcher =
47 ignoringParenImpCasts(declRefExpr(to(varDecl(hasType(isInteger()))))))
51 StatementMatcher LoopVarConversionMatcher =
52 implicitCastExpr(hasImplicitDestinationType(isInteger()),
53 has(ignoringParenImpCasts(LoopVarMatcher)))
54 .bind(LoopVarCastName);
58 StatementMatcher LoopBoundMatcher =
59 expr(ignoringParenImpCasts(allOf(hasType(isInteger()),
60 unless(integerLiteral()),
61 unless(hasType(isConstQualified())),
62 unless(hasType(enumType())))))
63 .bind(LoopUpperBoundName);
67 StatementMatcher IncrementMatcher =
68 expr(ignoringParenImpCasts(hasType(isInteger()))).bind(LoopIncrementName);
73 binaryOperator(hasOperatorName(
"<"),
74 hasLHS(LoopVarConversionMatcher),
75 hasRHS(LoopBoundMatcher)),
76 binaryOperator(hasOperatorName(
"<="),
77 hasLHS(LoopVarConversionMatcher),
78 hasRHS(LoopBoundMatcher)),
79 binaryOperator(hasOperatorName(
">"), hasLHS(LoopBoundMatcher),
80 hasRHS(LoopVarConversionMatcher)),
81 binaryOperator(hasOperatorName(
">="), hasLHS(LoopBoundMatcher),
82 hasRHS(LoopVarConversionMatcher)))),
83 hasIncrement(IncrementMatcher))
90 const QualType &IntExprType) {
91 assert(IntExprType->isIntegerType());
93 return IntExprType->isUnsignedIntegerType()
94 ? Context.getIntWidth(IntExprType)
95 : Context.getIntWidth(IntExprType) - 1;
101 const Expr *UpperBound,
102 const QualType &UpperBoundType) {
105 if (
const auto *BinOperator = dyn_cast<BinaryOperator>(UpperBound)) {
106 const Expr *RHSE = BinOperator->getRHS()->IgnoreParenImpCasts();
107 const Expr *LHSE = BinOperator->getLHS()->IgnoreParenImpCasts();
109 QualType RHSEType = RHSE->getType();
110 QualType LHSEType = LHSE->getType();
112 if (!RHSEType->isIntegerType() || !LHSEType->isIntegerType())
115 bool RHSEIsConstantValue = RHSEType->isEnumeralType() ||
116 RHSEType.isConstQualified() ||
117 isa<IntegerLiteral>(RHSE);
118 bool LHSEIsConstantValue = LHSEType->isEnumeralType() ||
119 LHSEType.isConstQualified() ||
120 isa<IntegerLiteral>(LHSE);
123 if (RHSEIsConstantValue && LHSEIsConstantValue)
125 if (RHSEIsConstantValue)
127 if (LHSEIsConstantValue)
137 void TooSmallLoopVariableCheck::check(
const MatchFinder::MatchResult &
Result) {
138 const auto *LoopVar = Result.Nodes.getNodeAs<Expr>(
LoopVarName);
139 const auto *UpperBound =
141 const auto *LoopIncrement =
145 if (LoopVar->getType() != LoopIncrement->getType())
148 QualType LoopVarType = LoopVar->getType();
149 QualType UpperBoundType = UpperBound->getType();
151 ASTContext &Context = *Result.Context;
154 unsigned UpperBoundPosBits =
157 if (UpperBoundPosBits == 0)
160 if (LoopVarPosBits < UpperBoundPosBits)
161 diag(LoopVar->getBeginLoc(),
"loop variable has narrower type %0 than " 162 "iteration's upper bound %1")
163 << LoopVarType << UpperBoundType;
static constexpr llvm::StringLiteral LoopVarName
static constexpr llvm::StringLiteral LoopName
static unsigned calcPositiveBits(const ASTContext &Context, const QualType &IntExprType)
Returns the positive part of the integer width for an integer type.
static constexpr llvm::StringLiteral LoopVarCastName
static constexpr llvm::StringLiteral LoopUpperBoundName
llvm::Optional< llvm::Expected< tooling::AtomicChanges > > Result
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
static unsigned calcUpperBoundPositiveBits(const ASTContext &Context, const Expr *UpperBound, const QualType &UpperBoundType)
Calculate the upper bound expression's positive bits, but ignore constant like values to reduce false...
static constexpr llvm::StringLiteral LoopIncrementName