Szelethus updated this revision to Diff 385459.
Szelethus edited the summary of this revision.
Szelethus added a comment.
Clarify the summary.
Delete unnecessary includes.
More fitting `iterator` names in the test files.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D113201/new/
https://reviews.llvm.org/D113201
Files:
clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.cpp
clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.h
clang-tools-extra/test/clang-tidy/checkers/Inputs/modernize-loop-convert/structures.h
clang-tools-extra/test/clang-tidy/checkers/modernize-loop-convert-basic.cpp
Index: clang-tools-extra/test/clang-tidy/checkers/modernize-loop-convert-basic.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/modernize-loop-convert-basic.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize-loop-convert-basic.cpp
@@ -273,6 +273,16 @@
// CHECK-FIXES: for (int & It : Tt)
// CHECK-FIXES-NEXT: printf("I found %d\n", It);
+ // Do not crash because of Qt.begin() converting. Q::iterator converts with a
+ // conversion operator, which has no name, to Q::const_iterator.
+ Q Qt;
+ for (Q::const_iterator It = Qt.begin(), E = Qt.end(); It != E; ++It) {
+ printf("I found %d\n", *It);
+ }
+ // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
+ // CHECK-FIXES: for (int & It : Qt)
+ // CHECK-FIXES-NEXT: printf("I found %d\n", It);
+
T *Pt;
for (T::iterator It = Pt->begin(), E = Pt->end(); It != E; ++It) {
printf("I found %d\n", *It);
Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/modernize-loop-convert/structures.h
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/Inputs/modernize-loop-convert/structures.h
+++ clang-tools-extra/test/clang-tidy/checkers/Inputs/modernize-loop-convert/structures.h
@@ -53,6 +53,23 @@
iterator end();
};
+struct Q {
+ typedef int value_type;
+ struct const_iterator {
+ value_type &operator*();
+ const value_type &operator*() const;
+ const_iterator &operator++();
+ bool operator!=(const const_iterator &other);
+ void insert(value_type);
+ value_type X;
+ };
+ struct iterator {
+ operator const_iterator() const;
+ };
+ iterator begin();
+ iterator end();
+};
+
struct U {
struct iterator {
Val& operator*();
Index: clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.h
===================================================================
--- clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.h
+++ clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.h
@@ -275,7 +275,7 @@
typedef llvm::SmallVector<Usage, 8> UsageResult;
// General functions used by ForLoopIndexUseVisitor and LoopConvertCheck.
-const Expr *digThroughConstructors(const Expr *E);
+const Expr *digThroughConstructorsConversions(const Expr *E);
bool areSameExpr(ASTContext *Context, const Expr *First, const Expr *Second);
const DeclRefExpr *getDeclRef(const Expr *E);
bool areSameVariable(const ValueDecl *First, const ValueDecl *Second);
Index: clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.cpp
===================================================================
--- clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.cpp
+++ clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.cpp
@@ -152,7 +152,7 @@
return true;
}
-/// Look through conversion/copy constructors to find the explicit
+/// Look through conversion/copy constructors and operators to find the explicit
/// initialization expression, returning it is found.
///
/// The main idea is that given
@@ -165,7 +165,7 @@
/// vector<int>::iterator it;
/// vector<int>::iterator it(v.begin(), 0); // if this constructor existed
/// as being initialized from `v.begin()`
-const Expr *digThroughConstructors(const Expr *E) {
+const Expr *digThroughConstructorsConversions(const Expr *E) {
if (!E)
return nullptr;
E = E->IgnoreImplicit();
@@ -178,8 +178,13 @@
E = ConstructExpr->getArg(0);
if (const auto *Temp = dyn_cast<MaterializeTemporaryExpr>(E))
E = Temp->getSubExpr();
- return digThroughConstructors(E);
+ return digThroughConstructorsConversions(E);
}
+ // If this is a conversion (as iterators commonly convert into their const
+ // iterator counterparts), dig through that as well.
+ if (const auto *ME = dyn_cast<CXXMemberCallExpr>(E))
+ if (const auto *D = dyn_cast<CXXConversionDecl>(ME->getMethodDecl()))
+ return digThroughConstructorsConversions(ME->getImplicitObjectArgument());
return E;
}
@@ -357,7 +362,7 @@
bool OnlyCasts = true;
const Expr *Init = VDecl->getInit()->IgnoreParenImpCasts();
if (isa_and_nonnull<CXXConstructExpr>(Init)) {
- Init = digThroughConstructors(Init);
+ Init = digThroughConstructorsConversions(Init);
OnlyCasts = false;
}
if (!Init)
Index: clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
+++ clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
@@ -304,8 +304,8 @@
static const Expr *getContainerFromBeginEndCall(const Expr *Init, bool IsBegin,
bool *IsArrow, bool IsReverse) {
// FIXME: Maybe allow declaration/initialization outside of the for loop.
- const auto *TheCall =
- dyn_cast_or_null<CXXMemberCallExpr>(digThroughConstructors(Init));
+ const auto *TheCall = dyn_cast_or_null<CXXMemberCallExpr>(
+ digThroughConstructorsConversions(Init));
if (!TheCall || TheCall->getNumArgs() != 0)
return nullptr;
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits