Skip to content

Commit d5d62a9

Browse files
committed
[Consumed][NFC] Refactor handleCall to take function argument list.
Differential Revision: https://reviews.llvm.org/D67569 llvm-svn: 373034
1 parent da963ab commit d5d62a9

File tree

4 files changed

+64
-24
lines changed

4 files changed

+64
-24
lines changed

‎clang/include/clang/AST/Stmt.h‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1041,7 +1041,8 @@ class alignas(void *) Stmt {
10411041
template<typename T, typename TPtr = T *, typename StmtPtr = Stmt *>
10421042
struct CastIterator
10431043
: llvm::iterator_adaptor_base<CastIterator<T, TPtr, StmtPtr>, StmtPtr *,
1044-
std::random_access_iterator_tag, TPtr> {
1044+
std::random_access_iterator_tag, TPtr,
1045+
int, void, TPtr> {
10451046
using Base = typename CastIterator::iterator_adaptor_base;
10461047

10471048
CastIterator() : Base(nullptr) {}

‎clang/lib/Analysis/Consumed.cpp‎

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -494,8 +494,10 @@ class ConsumedStmtVisitor : public ConstStmtVisitor<ConsumedStmtVisitor> {
494494
void checkCallability(const PropagationInfo &PInfo,
495495
const FunctionDecl *FunDecl,
496496
SourceLocation BlameLoc);
497-
bool handleCall(const CallExpr *Call, const Expr *ObjArg,
498-
const FunctionDecl *FunD);
497+
498+
using ArgRange = llvm::iterator_range<CallExpr::const_arg_iterator>;
499+
bool handleCall(const Expr *Call, const Expr *ObjArg,
500+
ArgRange args, const FunctionDecl *FunD);
499501

500502
void VisitBinaryOperator(const BinaryOperator *BinOp);
501503
void VisitCallExpr(const CallExpr *Call);
@@ -608,22 +610,21 @@ void ConsumedStmtVisitor::checkCallability(const PropagationInfo &PInfo,
608610
// Factors out common behavior for function, method, and operator calls.
609611
// Check parameters and set parameter state if necessary.
610612
// Returns true if the state of ObjArg is set, or false otherwise.
611-
bool ConsumedStmtVisitor::handleCall(const CallExpr *Call, const Expr *ObjArg,
613+
bool ConsumedStmtVisitor::handleCall(const Expr *Call,
614+
const Expr *ObjArg,
615+
ArgRange Args,
612616
const FunctionDecl *FunD) {
613-
unsigned Offset = 0;
614-
if (isa<CXXOperatorCallExpr>(Call) && isa<CXXMethodDecl>(FunD))
615-
Offset = 1; // first argument is 'this'
616-
617617
// check explicit parameters
618-
for (unsigned Index = Offset; Index < Call->getNumArgs(); ++Index) {
618+
unsigned Index = 0;
619+
for (const Expr *Arg : Args) {
619620
// Skip variable argument lists.
620-
if (Index - Offset >= FunD->getNumParams())
621+
if (Index >= FunD->getNumParams())
621622
break;
622623

623-
const ParmVarDecl *Param = FunD->getParamDecl(Index - Offset);
624+
const ParmVarDecl *Param = FunD->getParamDecl(Index++);
624625
QualType ParamType = Param->getType();
625626

626-
InfoEntry Entry = findInfo(Call->getArg(Index));
627+
InfoEntry Entry = findInfo(Arg);
627628

628629
if (Entry == PropagationMap.end() || Entry->second.isTest())
629630
continue;
@@ -636,7 +637,7 @@ bool ConsumedStmtVisitor::handleCall(const CallExpr *Call, const Expr *ObjArg,
636637

637638
if (ParamState != ExpectedState)
638639
Analyzer.WarningsHandler.warnParamTypestateMismatch(
639-
Call->getArg(Index)->getExprLoc(),
640+
Arg->getExprLoc(),
640641
stateToString(ExpectedState), stateToString(ParamState));
641642
}
642643

@@ -749,7 +750,7 @@ void ConsumedStmtVisitor::VisitCallExpr(const CallExpr *Call) {
749750
return;
750751
}
751752

752-
handleCall(Call, nullptr, FunDecl);
753+
handleCall(Call, nullptr, Call->arguments(), FunDecl);
753754
propagateReturnType(Call, FunDecl);
754755
}
755756

@@ -805,26 +806,28 @@ void ConsumedStmtVisitor::VisitCXXMemberCallExpr(
805806
if (!MD)
806807
return;
807808

808-
handleCall(Call, Call->getImplicitObjectArgument(), MD);
809+
handleCall(Call, Call->getImplicitObjectArgument(), Call->arguments(), MD);
809810
propagateReturnType(Call, MD);
810811
}
811812

812813
void ConsumedStmtVisitor::VisitCXXOperatorCallExpr(
813814
const CXXOperatorCallExpr *Call) {
814815
const auto *FunDecl = dyn_cast_or_null<FunctionDecl>(Call->getDirectCallee());
815816
if (!FunDecl) return;
817+
ArgRange Args = Call->arguments();
816818

817819
if (Call->getOperator() == OO_Equal) {
818-
ConsumedState CS = getInfo(Call->getArg(1));
819-
if (!handleCall(Call, Call->getArg(0), FunDecl))
820-
setInfo(Call->getArg(0), CS);
820+
ConsumedState CS = getInfo(llvm::index(Args, 1));
821+
if (!handleCall(Call, llvm::index(Args, 0), llvm::drop_begin(Args, 1),
822+
FunDecl))
823+
setInfo(llvm::index(Args, 0), CS);
821824
return;
822825
}
823826

824-
if (const auto *MCall = dyn_cast<CXXMemberCallExpr>(Call))
825-
handleCall(MCall, MCall->getImplicitObjectArgument(), FunDecl);
827+
if (isa<CXXMethodDecl>(FunDecl))
828+
handleCall(Call, llvm::index(Args, 0), llvm::drop_begin(Args, 1), FunDecl);
826829
else
827-
handleCall(Call, Call->getArg(0), FunDecl);
830+
handleCall(Call, nullptr, Args, FunDecl);
828831

829832
propagateReturnType(Call, FunDecl);
830833
}

‎llvm/include/llvm/ADT/STLExtras.h‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1573,6 +1573,14 @@ template <class Ptr> auto to_address(const Ptr &P) -> decltype(P.operator->()) {
15731573
}
15741574
template <class T> constexpr T *to_address(T *P) { return P; }
15751575

1576+
template <typename R>
1577+
auto index(R &&TheRange,
1578+
typename std::iterator_traits<detail::IterOfRange<R>>::difference_type N)
1579+
-> decltype(TheRange.begin()[N]) {
1580+
assert(N < TheRange.end() - TheRange.begin() && "Index out of range!");
1581+
return TheRange.begin()[N];
1582+
}
1583+
15761584
} // end namespace llvm
15771585

15781586
#endif // LLVM_ADT_STLEXTRAS_H

‎llvm/include/llvm/ADT/iterator_range.h‎

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,17 @@
2020

2121
#include <iterator>
2222
#include <utility>
23+
#include <cassert>
2324

2425
namespace llvm {
2526

27+
template <typename T>
28+
constexpr bool is_random_iterator() {
29+
return std::is_same<
30+
typename std::iterator_traits<T>::iterator_category,
31+
std::random_access_iterator_tag>::value;
32+
}
33+
2634
/// A range adaptor for a pair of iterators.
2735
///
2836
/// This just wraps two iterators into a range-compatible interface. Nothing
@@ -58,11 +66,31 @@ template <typename T> iterator_range<T> make_range(std::pair<T, T> p) {
5866
return iterator_range<T>(std::move(p.first), std::move(p.second));
5967
}
6068

69+
/// Non-random-iterator version
6170
template <typename T>
62-
iterator_range<decltype(adl_begin(std::declval<T>()))> drop_begin(T &&t,
63-
int n) {
64-
return make_range(std::next(adl_begin(t), n), adl_end(t));
71+
auto drop_begin(T &&t, int n) ->
72+
typename std::enable_if<!is_random_iterator<decltype(adl_begin(t))>(),
73+
iterator_range<decltype(adl_begin(t))>>::type {
74+
auto begin = adl_begin(t);
75+
auto end = adl_end(t);
76+
for (int i = 0; i < n; i++) {
77+
assert(begin != end);
78+
++begin;
79+
}
80+
return make_range(begin, end);
6581
}
82+
83+
/// Optimized version for random iterators
84+
template <typename T>
85+
auto drop_begin(T &&t, int n) ->
86+
typename std::enable_if<is_random_iterator<decltype(adl_begin(t))>(),
87+
iterator_range<decltype(adl_begin(t))>>::type {
88+
auto begin = adl_begin(t);
89+
auto end = adl_end(t);
90+
assert(end - begin >= n && "Dropping more elements than exist!");
91+
return make_range(std::next(begin, n), end);
92+
}
93+
6694
}
6795

6896
#endif

0 commit comments

Comments
 (0)