Index: clang-tidy/modernize/LoopConvertUtils.cpp =================================================================== --- clang-tidy/modernize/LoopConvertUtils.cpp +++ clang-tidy/modernize/LoopConvertUtils.cpp @@ -342,21 +342,27 @@ if (!VDecl->hasInit()) return false; - const Expr *Init = - digThroughConstructors(VDecl->getInit()->IgnoreParenImpCasts()); + bool OnlyCasts = true; + const Expr *Init = VDecl->getInit()->IgnoreParenImpCasts(); + if (Init && isa(Init)) { + Init = digThroughConstructors(Init); + OnlyCasts = false; + } if (!Init) return false; // Check that the declared type is the same as (or a reference to) the // container type. - QualType InitType = Init->getType(); - QualType DeclarationType = VDecl->getType(); - if (!DeclarationType.isNull() && DeclarationType->isReferenceType()) - DeclarationType = DeclarationType.getNonReferenceType(); + if (!OnlyCasts) { + QualType InitType = Init->getType(); + QualType DeclarationType = VDecl->getType(); + if (!DeclarationType.isNull() && DeclarationType->isReferenceType()) + DeclarationType = DeclarationType.getNonReferenceType(); - if (InitType.isNull() || DeclarationType.isNull() || - !Context->hasSameUnqualifiedType(DeclarationType, InitType)) - return false; + if (InitType.isNull() || DeclarationType.isNull() || + !Context->hasSameUnqualifiedType(DeclarationType, InitType)) + return false; + } switch (Init->getStmtClass()) { case Stmt::ArraySubscriptExprClass: { @@ -384,8 +390,8 @@ const auto *MemCall = cast(Init); // This check is needed because getMethodDecl can return nullptr if the // callee is a member function pointer. - if (MemCall->getMethodDecl() && - MemCall->getMethodDecl()->getName() == "at") { + const auto *MDecl = MemCall->getMethodDecl(); + if (MDecl && !isa(MDecl) && MDecl->getName() == "at") { assert(MemCall->getNumArgs() == 1); return isIndexInSubscriptExpr(MemCall->getArg(0), IndexVar); } Index: test/clang-tidy/modernize-loop-convert-extra.cpp =================================================================== --- test/clang-tidy/modernize-loop-convert-extra.cpp +++ test/clang-tidy/modernize-loop-convert-extra.cpp @@ -159,7 +159,7 @@ // CHECK-FIXES: for (int Alias : IntArr) // CHECK-FIXES-NEXT: for (unsigned J = 0; Alias; ++J) - struct IntRef { IntRef(const int& i); }; + struct IntRef { IntRef(); IntRef(const int& i); operator int*(); }; for (int I = 0; I < N; ++I) { IntRef Int(IntArr[I]); } @@ -167,6 +167,25 @@ // CHECK-FIXES: for (int I : IntArr) // CHECK-FIXES-NEXT: IntRef Int(I); + int *PtrArr[N]; + for (unsigned I = 0; I < N; ++I) { + const int* const P = PtrArr[I]; + printf("%d\n", *P); + } + // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead + // CHECK-FIXES: for (auto P : PtrArr) + // CHECK-FIXES-NEXT: printf("%d\n", *P); + + IntRef Refs[N]; + for (unsigned I = 0; I < N; ++I) { + int *P = Refs[I]; + printf("%d\n", *P); + } + // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead + // CHECK-FIXES: for (auto & Ref : Refs) + // CHECK-FIXES-NEXT: int *P = Ref; + // CHECK-FIXES-NEXT: printf("%d\n", *P); + // Ensure that removing the alias doesn't leave empty lines behind. for (int I = 0; I < N; ++I) { auto &X = IntArr[I];