Transform for loops over pseudo-arrays only if begin/end members exist
For loops using pseudo-arrays, classes that can be used like arrays from
the Loop Convert Transform's point of view, should only get transformed
if the pseudo-array class has begin()/end() members for the
range-based for-loop to call.
Free versions of begin()/end() should also be allowed but this is an
enhancement for another revision.
llvm-svn: 181539
diff --git a/clang-tools-extra/cpp11-migrate/LoopConvert/LoopMatchers.cpp b/clang-tools-extra/cpp11-migrate/LoopConvert/LoopMatchers.cpp
index a7ca15f..d69f2a8 100644
--- a/clang-tools-extra/cpp11-migrate/LoopConvert/LoopMatchers.cpp
+++ b/clang-tools-extra/cpp11-migrate/LoopConvert/LoopMatchers.cpp
@@ -258,10 +258,57 @@
/// - If the end iterator variable 'g' is defined, it is the same as 'j'
/// - The container's iterators would not be invalidated during the loop
StatementMatcher makePseudoArrayLoopMatcher() {
+ // Test that the incoming type has a record declaration that has methods
+ // called 'begin' and 'end'. If the incoming type is const, then make sure
+ // these methods are also marked const.
+ //
+ // FIXME: To be completely thorough this matcher should also ensure the
+ // return type of begin/end is an iterator that dereferences to the same as
+ // what operator[] or at() returns. Such a test isn't likely to fail except
+ // for pathological cases.
+ //
+ // FIXME: Also, a record doesn't necessarily need begin() and end(). Free
+ // functions called begin() and end() taking the container as an argument
+ // are also allowed.
+ TypeMatcher RecordWithBeginEnd =
+ qualType(anyOf(
+ qualType(
+ isConstQualified(),
+ hasDeclaration(
+ recordDecl(
+ hasMethod(
+ methodDecl(
+ hasName("begin"),
+ isConst()
+ )
+ ),
+ hasMethod(
+ methodDecl(
+ hasName("end"),
+ isConst()
+ )
+ )
+ )
+ ) // hasDeclaration
+ ), // qualType
+ qualType(
+ unless(isConstQualified()),
+ hasDeclaration(
+ recordDecl(
+ hasMethod(hasName("begin")),
+ hasMethod(hasName("end"))
+ )
+ )
+ ) // qualType
+ )
+ );
+
StatementMatcher SizeCallMatcher =
memberCallExpr(argumentCountIs(0),
callee(methodDecl(anyOf(hasName("size"),
- hasName("length")))));
+ hasName("length")))),
+ on(anyOf(hasType(pointsTo(RecordWithBeginEnd)),
+ hasType(RecordWithBeginEnd))));
StatementMatcher EndInitMatcher =
expr(anyOf(