1 //===--- LoopConvertUtils.cpp - clang-tidy --------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "LoopConvertUtils.h" 11 12 using namespace clang::ast_matchers; 13 using namespace clang::tooling; 14 using namespace clang; 15 using namespace llvm; 16 17 namespace clang { 18 namespace tidy { 19 namespace modernize { 20 21 /// \brief Tracks a stack of parent statements during traversal. 22 /// 23 /// All this really does is inject push_back() before running 24 /// RecursiveASTVisitor::TraverseStmt() and pop_back() afterwards. The Stmt atop 25 /// the stack is the parent of the current statement (NULL for the topmost 26 /// statement). 27 bool StmtAncestorASTVisitor::TraverseStmt(Stmt *Statement) { 28 StmtAncestors.insert(std::make_pair(Statement, StmtStack.back())); 29 StmtStack.push_back(Statement); 30 RecursiveASTVisitor<StmtAncestorASTVisitor>::TraverseStmt(Statement); 31 StmtStack.pop_back(); 32 return true; 33 } 34 35 /// \brief Keep track of the DeclStmt associated with each VarDecl. 36 /// 37 /// Combined with StmtAncestors, this provides roughly the same information as 38 /// Scope, as we can map a VarDecl to its DeclStmt, then walk up the parent tree 39 /// using StmtAncestors. 40 bool StmtAncestorASTVisitor::VisitDeclStmt(DeclStmt *Decls) { 41 for (const auto *decl : Decls->decls()) { 42 if (const auto *V = dyn_cast<VarDecl>(decl)) 43 DeclParents.insert(std::make_pair(V, Decls)); 44 } 45 return true; 46 } 47 48 /// \brief record the DeclRefExpr as part of the parent expression. 49 bool ComponentFinderASTVisitor::VisitDeclRefExpr(DeclRefExpr *E) { 50 Components.push_back(E); 51 return true; 52 } 53 54 /// \brief record the MemberExpr as part of the parent expression. 55 bool ComponentFinderASTVisitor::VisitMemberExpr(MemberExpr *Member) { 56 Components.push_back(Member); 57 return true; 58 } 59 60 /// \brief Forward any DeclRefExprs to a check on the referenced variable 61 /// declaration. 62 bool DependencyFinderASTVisitor::VisitDeclRefExpr(DeclRefExpr *DeclRef) { 63 if (auto *V = dyn_cast_or_null<VarDecl>(DeclRef->getDecl())) 64 return VisitVarDecl(V); 65 return true; 66 } 67 68 /// \brief Determine if any this variable is declared inside the ContainingStmt. 69 bool DependencyFinderASTVisitor::VisitVarDecl(VarDecl *V) { 70 const Stmt *Curr = DeclParents->lookup(V); 71 // First, see if the variable was declared within an inner scope of the loop. 72 while (Curr != nullptr) { 73 if (Curr == ContainingStmt) { 74 DependsOnInsideVariable = true; 75 return false; 76 } 77 Curr = StmtParents->lookup(Curr); 78 } 79 80 // Next, check if the variable was removed from existence by an earlier 81 // iteration. 82 for (const auto &I : *ReplacedVars) { 83 if (I.second == V) { 84 DependsOnInsideVariable = true; 85 return false; 86 } 87 } 88 return true; 89 } 90 91 /// \brief If we already created a variable for TheLoop, check to make sure 92 /// that the name was not already taken. 93 bool DeclFinderASTVisitor::VisitForStmt(ForStmt *TheLoop) { 94 StmtGeneratedVarNameMap::const_iterator I = GeneratedDecls->find(TheLoop); 95 if (I != GeneratedDecls->end() && I->second == Name) { 96 Found = true; 97 return false; 98 } 99 return true; 100 } 101 102 /// \brief If any named declaration within the AST subtree has the same name, 103 /// then consider Name already taken. 104 bool DeclFinderASTVisitor::VisitNamedDecl(NamedDecl *D) { 105 const IdentifierInfo *Ident = D->getIdentifier(); 106 if (Ident && Ident->getName() == Name) { 107 Found = true; 108 return false; 109 } 110 return true; 111 } 112 113 /// \brief Forward any declaration references to the actual check on the 114 /// referenced declaration. 115 bool DeclFinderASTVisitor::VisitDeclRefExpr(DeclRefExpr *DeclRef) { 116 if (auto *D = dyn_cast<NamedDecl>(DeclRef->getDecl())) 117 return VisitNamedDecl(D); 118 return true; 119 } 120 121 /// \brief If the new variable name conflicts with any type used in the loop, 122 /// then we mark that variable name as taken. 123 bool DeclFinderASTVisitor::VisitTypeLoc(TypeLoc TL) { 124 QualType QType = TL.getType(); 125 126 // Check if our name conflicts with a type, to handle for typedefs. 127 if (QType.getAsString() == Name) { 128 Found = true; 129 return false; 130 } 131 // Check for base type conflicts. For example, when a struct is being 132 // referenced in the body of the loop, the above getAsString() will return the 133 // whole type (ex. "struct s"), but will be caught here. 134 if (const IdentifierInfo *Ident = QType.getBaseTypeIdentifier()) { 135 if (Ident->getName() == Name) { 136 Found = true; 137 return false; 138 } 139 } 140 return true; 141 } 142 143 /// \brief Look through conversion/copy constructors to find the explicit 144 /// initialization expression, returning it is found. 145 /// 146 /// The main idea is that given 147 /// vector<int> v; 148 /// we consider either of these initializations 149 /// vector<int>::iterator it = v.begin(); 150 /// vector<int>::iterator it(v.begin()); 151 /// and retrieve `v.begin()` as the expression used to initialize `it` but do 152 /// not include 153 /// vector<int>::iterator it; 154 /// vector<int>::iterator it(v.begin(), 0); // if this constructor existed 155 /// as being initialized from `v.begin()` 156 const Expr *digThroughConstructors(const Expr *E) { 157 if (!E) 158 return nullptr; 159 E = E->IgnoreParenImpCasts(); 160 if (const auto *ConstructExpr = dyn_cast<CXXConstructExpr>(E)) { 161 // The initial constructor must take exactly one parameter, but base class 162 // and deferred constructors can take more. 163 if (ConstructExpr->getNumArgs() != 1 || 164 ConstructExpr->getConstructionKind() != CXXConstructExpr::CK_Complete) 165 return nullptr; 166 E = ConstructExpr->getArg(0); 167 if (const auto *Temp = dyn_cast<MaterializeTemporaryExpr>(E)) 168 E = Temp->GetTemporaryExpr(); 169 return digThroughConstructors(E); 170 } 171 return E; 172 } 173 174 /// \brief Returns true when two Exprs are equivalent. 175 bool areSameExpr(ASTContext *Context, const Expr *First, const Expr *Second) { 176 if (!First || !Second) 177 return false; 178 179 llvm::FoldingSetNodeID FirstID, SecondID; 180 First->Profile(FirstID, *Context, true); 181 Second->Profile(SecondID, *Context, true); 182 return FirstID == SecondID; 183 } 184 185 /// \brief Returns the DeclRefExpr represented by E, or NULL if there isn't one. 186 const DeclRefExpr *getDeclRef(const Expr *E) { 187 return dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()); 188 } 189 190 /// \brief Returns true when two ValueDecls are the same variable. 191 bool areSameVariable(const ValueDecl *First, const ValueDecl *Second) { 192 return First && Second && 193 First->getCanonicalDecl() == Second->getCanonicalDecl(); 194 } 195 196 /// \brief Determines if an expression is a declaration reference to a 197 /// particular variable. 198 static bool exprReferencesVariable(const ValueDecl *Target, const Expr *E) { 199 if (!Target || !E) 200 return false; 201 const DeclRefExpr *Decl = getDeclRef(E); 202 return Decl && areSameVariable(Target, Decl->getDecl()); 203 } 204 205 /// \brief If the expression is a dereference or call to operator*(), return the 206 /// operand. Otherwise, return NULL. 207 static const Expr *getDereferenceOperand(const Expr *E) { 208 if (const auto *Uop = dyn_cast<UnaryOperator>(E)) 209 return Uop->getOpcode() == UO_Deref ? Uop->getSubExpr() : nullptr; 210 211 if (const auto *OpCall = dyn_cast<CXXOperatorCallExpr>(E)) { 212 return OpCall->getOperator() == OO_Star && OpCall->getNumArgs() == 1 213 ? OpCall->getArg(0) 214 : nullptr; 215 } 216 217 return nullptr; 218 } 219 220 /// \brief Returns true when the Container contains an Expr equivalent to E. 221 template <typename ContainerT> 222 static bool containsExpr(ASTContext *Context, const ContainerT *Container, 223 const Expr *E) { 224 llvm::FoldingSetNodeID ID; 225 E->Profile(ID, *Context, true); 226 for (const auto &I : *Container) { 227 if (ID == I.second) 228 return true; 229 } 230 return false; 231 } 232 233 /// \brief Returns true when the index expression is a declaration reference to 234 /// IndexVar. 235 /// 236 /// If the index variable is `index`, this function returns true on 237 /// arrayExpression[index]; 238 /// containerExpression[index]; 239 /// but not 240 /// containerExpression[notIndex]; 241 static bool isIndexInSubscriptExpr(const Expr *IndexExpr, 242 const VarDecl *IndexVar) { 243 const DeclRefExpr *Idx = getDeclRef(IndexExpr); 244 return Idx && Idx->getType()->isIntegerType() && 245 areSameVariable(IndexVar, Idx->getDecl()); 246 } 247 248 /// \brief Returns true when the index expression is a declaration reference to 249 /// IndexVar, Obj is the same expression as SourceExpr after all parens and 250 /// implicit casts are stripped off. 251 /// 252 /// If PermitDeref is true, IndexExpression may 253 /// be a dereference (overloaded or builtin operator*). 254 /// 255 /// This function is intended for array-like containers, as it makes sure that 256 /// both the container and the index match. 257 /// If the loop has index variable `index` and iterates over `container`, then 258 /// isIndexInSubscriptExpr returns true for 259 /// \code 260 /// container[index] 261 /// container.at(index) 262 /// container->at(index) 263 /// \endcode 264 /// but not for 265 /// \code 266 /// container[notIndex] 267 /// notContainer[index] 268 /// \endcode 269 /// If PermitDeref is true, then isIndexInSubscriptExpr additionally returns 270 /// true on these expressions: 271 /// \code 272 /// (*container)[index] 273 /// (*container).at(index) 274 /// \endcode 275 static bool isIndexInSubscriptExpr(ASTContext *Context, const Expr *IndexExpr, 276 const VarDecl *IndexVar, const Expr *Obj, 277 const Expr *SourceExpr, bool PermitDeref) { 278 if (!SourceExpr || !Obj || !isIndexInSubscriptExpr(IndexExpr, IndexVar)) 279 return false; 280 281 if (areSameExpr(Context, SourceExpr->IgnoreParenImpCasts(), 282 Obj->IgnoreParenImpCasts())) 283 return true; 284 285 if (const Expr *InnerObj = getDereferenceOperand(Obj->IgnoreParenImpCasts())) 286 if (PermitDeref && areSameExpr(Context, SourceExpr->IgnoreParenImpCasts(), 287 InnerObj->IgnoreParenImpCasts())) 288 return true; 289 290 return false; 291 } 292 293 /// \brief Returns true when Opcall is a call a one-parameter dereference of 294 /// IndexVar. 295 /// 296 /// For example, if the index variable is `index`, returns true for 297 /// *index 298 /// but not 299 /// index 300 /// *notIndex 301 static bool isDereferenceOfOpCall(const CXXOperatorCallExpr *OpCall, 302 const VarDecl *IndexVar) { 303 return OpCall->getOperator() == OO_Star && OpCall->getNumArgs() == 1 && 304 exprReferencesVariable(IndexVar, OpCall->getArg(0)); 305 } 306 307 /// \brief Returns true when Uop is a dereference of IndexVar. 308 /// 309 /// For example, if the index variable is `index`, returns true for 310 /// *index 311 /// but not 312 /// index 313 /// *notIndex 314 static bool isDereferenceOfUop(const UnaryOperator *Uop, 315 const VarDecl *IndexVar) { 316 return Uop->getOpcode() == UO_Deref && 317 exprReferencesVariable(IndexVar, Uop->getSubExpr()); 318 } 319 320 /// \brief Determines whether the given Decl defines a variable initialized to 321 /// the loop object. 322 /// 323 /// This is intended to find cases such as 324 /// \code 325 /// for (int i = 0; i < arraySize(arr); ++i) { 326 /// T t = arr[i]; 327 /// // use t, do not use i 328 /// } 329 /// \endcode 330 /// and 331 /// \code 332 /// for (iterator i = container.begin(), e = container.end(); i != e; ++i) { 333 /// T t = *i; 334 /// // use t, do not use i 335 /// } 336 /// \endcode 337 static bool isAliasDecl(ASTContext *Context, const Decl *TheDecl, 338 const VarDecl *IndexVar) { 339 const auto *VDecl = dyn_cast<VarDecl>(TheDecl); 340 if (!VDecl) 341 return false; 342 if (!VDecl->hasInit()) 343 return false; 344 345 bool OnlyCasts = true; 346 const Expr *Init = VDecl->getInit()->IgnoreParenImpCasts(); 347 if (Init && isa<CXXConstructExpr>(Init)) { 348 Init = digThroughConstructors(Init); 349 OnlyCasts = false; 350 } 351 if (!Init) 352 return false; 353 354 // Check that the declared type is the same as (or a reference to) the 355 // container type. 356 if (!OnlyCasts) { 357 QualType InitType = Init->getType(); 358 QualType DeclarationType = VDecl->getType(); 359 if (!DeclarationType.isNull() && DeclarationType->isReferenceType()) 360 DeclarationType = DeclarationType.getNonReferenceType(); 361 362 if (InitType.isNull() || DeclarationType.isNull() || 363 !Context->hasSameUnqualifiedType(DeclarationType, InitType)) 364 return false; 365 } 366 367 switch (Init->getStmtClass()) { 368 case Stmt::ArraySubscriptExprClass: { 369 const auto *E = cast<ArraySubscriptExpr>(Init); 370 // We don't really care which array is used here. We check to make sure 371 // it was the correct one later, since the AST will traverse it next. 372 return isIndexInSubscriptExpr(E->getIdx(), IndexVar); 373 } 374 375 case Stmt::UnaryOperatorClass: 376 return isDereferenceOfUop(cast<UnaryOperator>(Init), IndexVar); 377 378 case Stmt::CXXOperatorCallExprClass: { 379 const auto *OpCall = cast<CXXOperatorCallExpr>(Init); 380 if (OpCall->getOperator() == OO_Star) 381 return isDereferenceOfOpCall(OpCall, IndexVar); 382 if (OpCall->getOperator() == OO_Subscript) { 383 assert(OpCall->getNumArgs() == 2); 384 return isIndexInSubscriptExpr(OpCall->getArg(1), IndexVar); 385 } 386 break; 387 } 388 389 case Stmt::CXXMemberCallExprClass: { 390 const auto *MemCall = cast<CXXMemberCallExpr>(Init); 391 // This check is needed because getMethodDecl can return nullptr if the 392 // callee is a member function pointer. 393 const auto *MDecl = MemCall->getMethodDecl(); 394 if (MDecl && !isa<CXXConversionDecl>(MDecl) && 395 MDecl->getNameAsString() == "at" && MemCall->getNumArgs() == 1) { 396 return isIndexInSubscriptExpr(MemCall->getArg(0), IndexVar); 397 } 398 return false; 399 } 400 401 default: 402 break; 403 } 404 return false; 405 } 406 407 /// \brief Determines whether the bound of a for loop condition expression is 408 /// the same as the statically computable size of ArrayType. 409 /// 410 /// Given 411 /// \code 412 /// const int N = 5; 413 /// int arr[N]; 414 /// \endcode 415 /// This is intended to permit 416 /// \code 417 /// for (int i = 0; i < N; ++i) { /* use arr[i] */ } 418 /// for (int i = 0; i < arraysize(arr); ++i) { /* use arr[i] */ } 419 /// \endcode 420 static bool arrayMatchesBoundExpr(ASTContext *Context, 421 const QualType &ArrayType, 422 const Expr *ConditionExpr) { 423 if (!ConditionExpr || ConditionExpr->isValueDependent()) 424 return false; 425 const ConstantArrayType *ConstType = 426 Context->getAsConstantArrayType(ArrayType); 427 if (!ConstType) 428 return false; 429 llvm::APSInt ConditionSize; 430 if (!ConditionExpr->isIntegerConstantExpr(ConditionSize, *Context)) 431 return false; 432 llvm::APSInt ArraySize(ConstType->getSize()); 433 return llvm::APSInt::isSameValue(ConditionSize, ArraySize); 434 } 435 436 ForLoopIndexUseVisitor::ForLoopIndexUseVisitor(ASTContext *Context, 437 const VarDecl *IndexVar, 438 const VarDecl *EndVar, 439 const Expr *ContainerExpr, 440 const Expr *ArrayBoundExpr, 441 bool ContainerNeedsDereference) 442 : Context(Context), IndexVar(IndexVar), EndVar(EndVar), 443 ContainerExpr(ContainerExpr), ArrayBoundExpr(ArrayBoundExpr), 444 ContainerNeedsDereference(ContainerNeedsDereference), 445 OnlyUsedAsIndex(true), AliasDecl(nullptr), 446 ConfidenceLevel(Confidence::CL_Safe), NextStmtParent(nullptr), 447 CurrStmtParent(nullptr), ReplaceWithAliasUse(false), 448 AliasFromForInit(false) { 449 if (ContainerExpr) 450 addComponent(ContainerExpr); 451 } 452 453 bool ForLoopIndexUseVisitor::findAndVerifyUsages(const Stmt *Body) { 454 TraverseStmt(const_cast<Stmt *>(Body)); 455 return OnlyUsedAsIndex && ContainerExpr; 456 } 457 458 void ForLoopIndexUseVisitor::addComponents(const ComponentVector &Components) { 459 // FIXME: add sort(on ID)+unique to avoid extra work. 460 for (const auto &I : Components) 461 addComponent(I); 462 } 463 464 void ForLoopIndexUseVisitor::addComponent(const Expr *E) { 465 FoldingSetNodeID ID; 466 const Expr *Node = E->IgnoreParenImpCasts(); 467 Node->Profile(ID, *Context, true); 468 DependentExprs.push_back(std::make_pair(Node, ID)); 469 } 470 471 void ForLoopIndexUseVisitor::addUsage(const Usage &U) { 472 SourceLocation Begin = U.Range.getBegin(); 473 if (Begin.isMacroID()) 474 Begin = Context->getSourceManager().getSpellingLoc(Begin); 475 476 if (UsageLocations.insert(Begin).second) 477 Usages.push_back(U); 478 } 479 480 /// \brief If the unary operator is a dereference of IndexVar, include it 481 /// as a valid usage and prune the traversal. 482 /// 483 /// For example, if container.begin() and container.end() both return pointers 484 /// to int, this makes sure that the initialization for `k` is not counted as an 485 /// unconvertible use of the iterator `i`. 486 /// \code 487 /// for (int *i = container.begin(), *e = container.end(); i != e; ++i) { 488 /// int k = *i + 2; 489 /// } 490 /// \endcode 491 bool ForLoopIndexUseVisitor::TraverseUnaryDeref(UnaryOperator *Uop) { 492 // If we dereference an iterator that's actually a pointer, count the 493 // occurrence. 494 if (isDereferenceOfUop(Uop, IndexVar)) { 495 addUsage(Usage(Uop)); 496 return true; 497 } 498 499 return VisitorBase::TraverseUnaryOperator(Uop); 500 } 501 502 /// \brief If the member expression is operator-> (overloaded or not) on 503 /// IndexVar, include it as a valid usage and prune the traversal. 504 /// 505 /// For example, given 506 /// \code 507 /// struct Foo { int bar(); int x; }; 508 /// vector<Foo> v; 509 /// \endcode 510 /// the following uses will be considered convertible: 511 /// \code 512 /// for (vector<Foo>::iterator i = v.begin(), e = v.end(); i != e; ++i) { 513 /// int b = i->bar(); 514 /// int k = i->x + 1; 515 /// } 516 /// \endcode 517 /// though 518 /// \code 519 /// for (vector<Foo>::iterator i = v.begin(), e = v.end(); i != e; ++i) { 520 /// int k = i.insert(1); 521 /// } 522 /// for (vector<Foo>::iterator i = v.begin(), e = v.end(); i != e; ++i) { 523 /// int b = e->bar(); 524 /// } 525 /// \endcode 526 /// will not. 527 bool ForLoopIndexUseVisitor::TraverseMemberExpr(MemberExpr *Member) { 528 const Expr *Base = Member->getBase(); 529 const DeclRefExpr *Obj = getDeclRef(Base); 530 const Expr *ResultExpr = Member; 531 QualType ExprType; 532 if (const auto *Call = 533 dyn_cast<CXXOperatorCallExpr>(Base->IgnoreParenImpCasts())) { 534 // If operator->() is a MemberExpr containing a CXXOperatorCallExpr, then 535 // the MemberExpr does not have the expression we want. We therefore catch 536 // that instance here. 537 // For example, if vector<Foo>::iterator defines operator->(), then the 538 // example `i->bar()` at the top of this function is a CXXMemberCallExpr 539 // referring to `i->` as the member function called. We want just `i`, so 540 // we take the argument to operator->() as the base object. 541 if (Call->getOperator() == OO_Arrow) { 542 assert(Call->getNumArgs() == 1 && 543 "Operator-> takes more than one argument"); 544 Obj = getDeclRef(Call->getArg(0)); 545 ResultExpr = Obj; 546 ExprType = Call->getCallReturnType(*Context); 547 } 548 } 549 550 if (Obj && exprReferencesVariable(IndexVar, Obj)) { 551 // Member calls on the iterator with '.' are not allowed. 552 if (!Member->isArrow()) { 553 OnlyUsedAsIndex = false; 554 return true; 555 } 556 557 if (ExprType.isNull()) 558 ExprType = Obj->getType(); 559 560 if (!ExprType->isPointerType()) 561 return false; 562 563 // FIXME: This works around not having the location of the arrow operator. 564 // Consider adding OperatorLoc to MemberExpr? 565 SourceLocation ArrowLoc = Lexer::getLocForEndOfToken( 566 Base->getExprLoc(), 0, Context->getSourceManager(), 567 Context->getLangOpts()); 568 // If something complicated is happening (i.e. the next token isn't an 569 // arrow), give up on making this work. 570 if (ArrowLoc.isValid()) { 571 addUsage(Usage(ResultExpr, Usage::UK_MemberThroughArrow, 572 SourceRange(Base->getExprLoc(), ArrowLoc))); 573 return true; 574 } 575 } 576 return VisitorBase::TraverseMemberExpr(Member); 577 } 578 579 /// \brief If a member function call is the at() accessor on the container with 580 /// IndexVar as the single argument, include it as a valid usage and prune 581 /// the traversal. 582 /// 583 /// Member calls on other objects will not be permitted. 584 /// Calls on the iterator object are not permitted, unless done through 585 /// operator->(). The one exception is allowing vector::at() for pseudoarrays. 586 bool ForLoopIndexUseVisitor::TraverseCXXMemberCallExpr( 587 CXXMemberCallExpr *MemberCall) { 588 auto *Member = 589 dyn_cast<MemberExpr>(MemberCall->getCallee()->IgnoreParenImpCasts()); 590 if (!Member) 591 return VisitorBase::TraverseCXXMemberCallExpr(MemberCall); 592 593 // We specifically allow an accessor named "at" to let STL in, though 594 // this is restricted to pseudo-arrays by requiring a single, integer 595 // argument. 596 const IdentifierInfo *Ident = Member->getMemberDecl()->getIdentifier(); 597 if (Ident && Ident->isStr("at") && MemberCall->getNumArgs() == 1) { 598 if (isIndexInSubscriptExpr(Context, MemberCall->getArg(0), IndexVar, 599 Member->getBase(), ContainerExpr, 600 ContainerNeedsDereference)) { 601 addUsage(Usage(MemberCall)); 602 return true; 603 } 604 } 605 606 if (containsExpr(Context, &DependentExprs, Member->getBase())) 607 ConfidenceLevel.lowerTo(Confidence::CL_Risky); 608 609 return VisitorBase::TraverseCXXMemberCallExpr(MemberCall); 610 } 611 612 /// \brief If an overloaded operator call is a dereference of IndexVar or 613 /// a subscript of the container with IndexVar as the single argument, 614 /// include it as a valid usage and prune the traversal. 615 /// 616 /// For example, given 617 /// \code 618 /// struct Foo { int bar(); int x; }; 619 /// vector<Foo> v; 620 /// void f(Foo); 621 /// \endcode 622 /// the following uses will be considered convertible: 623 /// \code 624 /// for (vector<Foo>::iterator i = v.begin(), e = v.end(); i != e; ++i) { 625 /// f(*i); 626 /// } 627 /// for (int i = 0; i < v.size(); ++i) { 628 /// int i = v[i] + 1; 629 /// } 630 /// \endcode 631 bool ForLoopIndexUseVisitor::TraverseCXXOperatorCallExpr( 632 CXXOperatorCallExpr *OpCall) { 633 switch (OpCall->getOperator()) { 634 case OO_Star: 635 if (isDereferenceOfOpCall(OpCall, IndexVar)) { 636 addUsage(Usage(OpCall)); 637 return true; 638 } 639 break; 640 641 case OO_Subscript: 642 if (OpCall->getNumArgs() != 2) 643 break; 644 if (isIndexInSubscriptExpr(Context, OpCall->getArg(1), IndexVar, 645 OpCall->getArg(0), ContainerExpr, 646 ContainerNeedsDereference)) { 647 addUsage(Usage(OpCall)); 648 return true; 649 } 650 break; 651 652 default: 653 break; 654 } 655 return VisitorBase::TraverseCXXOperatorCallExpr(OpCall); 656 } 657 658 /// \brief If we encounter an array with IndexVar as the index of an 659 /// ArraySubsriptExpression, note it as a consistent usage and prune the 660 /// AST traversal. 661 /// 662 /// For example, given 663 /// \code 664 /// const int N = 5; 665 /// int arr[N]; 666 /// \endcode 667 /// This is intended to permit 668 /// \code 669 /// for (int i = 0; i < N; ++i) { /* use arr[i] */ } 670 /// \endcode 671 /// but not 672 /// \code 673 /// for (int i = 0; i < N; ++i) { /* use notArr[i] */ } 674 /// \endcode 675 /// and further checking needs to be done later to ensure that exactly one array 676 /// is referenced. 677 bool ForLoopIndexUseVisitor::TraverseArraySubscriptExpr(ArraySubscriptExpr *E) { 678 Expr *Arr = E->getBase(); 679 if (!isIndexInSubscriptExpr(E->getIdx(), IndexVar)) 680 return VisitorBase::TraverseArraySubscriptExpr(E); 681 682 if ((ContainerExpr && 683 !areSameExpr(Context, Arr->IgnoreParenImpCasts(), 684 ContainerExpr->IgnoreParenImpCasts())) || 685 !arrayMatchesBoundExpr(Context, Arr->IgnoreImpCasts()->getType(), 686 ArrayBoundExpr)) { 687 // If we have already discovered the array being indexed and this isn't it 688 // or this array doesn't match, mark this loop as unconvertible. 689 OnlyUsedAsIndex = false; 690 return VisitorBase::TraverseArraySubscriptExpr(E); 691 } 692 693 if (!ContainerExpr) 694 ContainerExpr = Arr; 695 696 addUsage(Usage(E)); 697 return true; 698 } 699 700 /// \brief If we encounter a reference to IndexVar in an unpruned branch of the 701 /// traversal, mark this loop as unconvertible. 702 /// 703 /// This implements the whitelist for convertible loops: any usages of IndexVar 704 /// not explicitly considered convertible by this traversal will be caught by 705 /// this function. 706 /// 707 /// Additionally, if the container expression is more complex than just a 708 /// DeclRefExpr, and some part of it is appears elsewhere in the loop, lower 709 /// our confidence in the transformation. 710 /// 711 /// For example, these are not permitted: 712 /// \code 713 /// for (int i = 0; i < N; ++i) { printf("arr[%d] = %d", i, arr[i]); } 714 /// for (vector<int>::iterator i = container.begin(), e = container.end(); 715 /// i != e; ++i) 716 /// i.insert(0); 717 /// for (vector<int>::iterator i = container.begin(), e = container.end(); 718 /// i != e; ++i) 719 /// if (i + 1 != e) 720 /// printf("%d", *i); 721 /// \endcode 722 /// 723 /// And these will raise the risk level: 724 /// \code 725 /// int arr[10][20]; 726 /// int l = 5; 727 /// for (int j = 0; j < 20; ++j) 728 /// int k = arr[l][j] + l; // using l outside arr[l] is considered risky 729 /// for (int i = 0; i < obj.getVector().size(); ++i) 730 /// obj.foo(10); // using `obj` is considered risky 731 /// \endcode 732 bool ForLoopIndexUseVisitor::VisitDeclRefExpr(DeclRefExpr *E) { 733 const ValueDecl *TheDecl = E->getDecl(); 734 if (areSameVariable(IndexVar, TheDecl) || 735 exprReferencesVariable(IndexVar, E) || areSameVariable(EndVar, TheDecl) || 736 exprReferencesVariable(EndVar, E)) 737 OnlyUsedAsIndex = false; 738 if (containsExpr(Context, &DependentExprs, E)) 739 ConfidenceLevel.lowerTo(Confidence::CL_Risky); 740 return true; 741 } 742 743 /// \brief If the loop index is captured by a lambda, replace this capture 744 /// by the range-for loop variable. 745 /// 746 /// For example: 747 /// \code 748 /// for (int i = 0; i < N; ++i) { 749 /// auto f = [v, i](int k) { 750 /// printf("%d\n", v[i] + k); 751 /// }; 752 /// f(v[i]); 753 /// } 754 /// \endcode 755 /// 756 /// Will be replaced by: 757 /// \code 758 /// for (auto & elem : v) { 759 /// auto f = [v, elem](int k) { 760 /// printf("%d\n", elem + k); 761 /// }; 762 /// f(elem); 763 /// } 764 /// \endcode 765 bool ForLoopIndexUseVisitor::TraverseLambdaCapture(LambdaExpr *LE, 766 const LambdaCapture *C) { 767 if (C->capturesVariable()) { 768 const VarDecl *VDecl = C->getCapturedVar(); 769 if (areSameVariable(IndexVar, cast<ValueDecl>(VDecl))) { 770 // FIXME: if the index is captured, it will count as an usage and the 771 // alias (if any) won't work, because it is only used in case of having 772 // exactly one usage. 773 addUsage(Usage(nullptr, 774 C->getCaptureKind() == LCK_ByCopy ? Usage::UK_CaptureByCopy 775 : Usage::UK_CaptureByRef, 776 C->getLocation())); 777 } 778 } 779 return VisitorBase::TraverseLambdaCapture(LE, C); 780 } 781 782 /// \brief If we find that another variable is created just to refer to the loop 783 /// element, note it for reuse as the loop variable. 784 /// 785 /// See the comments for isAliasDecl. 786 bool ForLoopIndexUseVisitor::VisitDeclStmt(DeclStmt *S) { 787 if (!AliasDecl && S->isSingleDecl() && 788 isAliasDecl(Context, S->getSingleDecl(), IndexVar)) { 789 AliasDecl = S; 790 if (CurrStmtParent) { 791 if (isa<IfStmt>(CurrStmtParent) || isa<WhileStmt>(CurrStmtParent) || 792 isa<SwitchStmt>(CurrStmtParent)) 793 ReplaceWithAliasUse = true; 794 else if (isa<ForStmt>(CurrStmtParent)) { 795 if (cast<ForStmt>(CurrStmtParent)->getConditionVariableDeclStmt() == S) 796 ReplaceWithAliasUse = true; 797 else 798 // It's assumed S came the for loop's init clause. 799 AliasFromForInit = true; 800 } 801 } 802 } 803 804 return true; 805 } 806 807 bool ForLoopIndexUseVisitor::TraverseStmt(Stmt *S) { 808 // All this pointer swapping is a mechanism for tracking immediate parentage 809 // of Stmts. 810 const Stmt *OldNextParent = NextStmtParent; 811 CurrStmtParent = NextStmtParent; 812 NextStmtParent = S; 813 bool Result = VisitorBase::TraverseStmt(S); 814 NextStmtParent = OldNextParent; 815 return Result; 816 } 817 818 std::string VariableNamer::createIndexName() { 819 // FIXME: Add in naming conventions to handle: 820 // - How to handle conflicts. 821 // - An interactive process for naming. 822 std::string IteratorName; 823 StringRef ContainerName; 824 if (TheContainer) 825 ContainerName = TheContainer->getName(); 826 827 size_t Len = ContainerName.size(); 828 if (Len > 1 && ContainerName.endswith(Style == NS_UpperCase ? "S" : "s")) { 829 IteratorName = ContainerName.substr(0, Len - 1); 830 // E.g.: (auto thing : things) 831 if (!declarationExists(IteratorName) || IteratorName == OldIndex->getName()) 832 return IteratorName; 833 } 834 835 if (Len > 2 && ContainerName.endswith(Style == NS_UpperCase ? "S_" : "s_")) { 836 IteratorName = ContainerName.substr(0, Len - 2); 837 // E.g.: (auto thing : things_) 838 if (!declarationExists(IteratorName) || IteratorName == OldIndex->getName()) 839 return IteratorName; 840 } 841 842 return OldIndex->getName(); 843 } 844 845 /// \brief Determines whether or not the the name \a Symbol conflicts with 846 /// language keywords or defined macros. Also checks if the name exists in 847 /// LoopContext, any of its parent contexts, or any of its child statements. 848 /// 849 /// We also check to see if the same identifier was generated by this loop 850 /// converter in a loop nested within SourceStmt. 851 bool VariableNamer::declarationExists(StringRef Symbol) { 852 assert(Context != nullptr && "Expected an ASTContext"); 853 IdentifierInfo &Ident = Context->Idents.get(Symbol); 854 855 // Check if the symbol is not an identifier (ie. is a keyword or alias). 856 if (!isAnyIdentifier(Ident.getTokenID())) 857 return true; 858 859 // Check for conflicting macro definitions. 860 if (Ident.hasMacroDefinition()) 861 return true; 862 863 // Determine if the symbol was generated in a parent context. 864 for (const Stmt *S = SourceStmt; S != nullptr; S = ReverseAST->lookup(S)) { 865 StmtGeneratedVarNameMap::const_iterator I = GeneratedDecls->find(S); 866 if (I != GeneratedDecls->end() && I->second == Symbol) 867 return true; 868 } 869 870 // FIXME: Rather than detecting conflicts at their usages, we should check the 871 // parent context. 872 // For some reason, lookup() always returns the pair (NULL, NULL) because its 873 // StoredDeclsMap is not initialized (i.e. LookupPtr.getInt() is false inside 874 // of DeclContext::lookup()). Why is this? 875 876 // Finally, determine if the symbol was used in the loop or a child context. 877 DeclFinderASTVisitor DeclFinder(Symbol, GeneratedDecls); 878 return DeclFinder.findUsages(SourceStmt); 879 } 880 881 std::string VariableNamer::AppendWithStyle(StringRef Str, 882 StringRef Suffix) const { 883 std::string Name = Str; 884 if (!Suffix.empty()) { 885 if (Style == NS_LowerCase || Style == NS_UpperCase) 886 Name += "_"; 887 int SuffixStart = Name.size(); 888 Name += Suffix; 889 if (Style == NS_CamelBack) 890 Name[SuffixStart] = toupper(Name[SuffixStart]); 891 } 892 return Name; 893 } 894 895 } // namespace modernize 896 } // namespace tidy 897 } // namespace clang 898