- Fixed comments
  - Used clang-format on the code
  - Added asserts

Hi revane,

http://llvm-reviews.chandlerc.com/D759

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D759?vs=1862&id=1884#toc

Files:
  cpp11-migrate/LoopConvert/LoopActions.cpp
  cpp11-migrate/LoopConvert/LoopActions.h
  cpp11-migrate/LoopConvert/LoopMatchers.cpp
  cpp11-migrate/LoopConvert/LoopMatchers.h
  test/cpp11-migrate/LoopConvert/Inputs/structures.h
  test/cpp11-migrate/LoopConvert/iterator.cpp
  test/cpp11-migrate/LoopConvert/naming-conflict.cpp
  test/cpp11-migrate/LoopConvert/nesting.cpp
  test/cpp11-migrate/LoopConvert/single-iterator.cpp
Index: cpp11-migrate/LoopConvert/LoopActions.cpp
===================================================================
--- cpp11-migrate/LoopConvert/LoopActions.cpp
+++ cpp11-migrate/LoopConvert/LoopActions.cpp
@@ -29,9 +29,9 @@
   SourceRange Range;
 
   explicit Usage(const Expr *E)
-      : E(E), IsArrow(false), Range(E->getSourceRange()) { }
+      : E(E), IsArrow(false), Range(E->getSourceRange()) {}
   Usage(const Expr *E, bool IsArrow, SourceRange Range)
-      : E(E), IsArrow(IsArrow), Range(Range) { }
+      : E(E), IsArrow(IsArrow), Range(Range) {}
 };
 
 /// \brief A class to encapsulate lowering of the tool's confidence level.
@@ -42,8 +42,7 @@
 class Confidence {
 public:
   /// \brief Initialize confidence level.
-  explicit Confidence(RiskLevel Level) :
-    CurrentLevel(Level) {}
+  explicit Confidence(RiskLevel Level) : CurrentLevel(Level) {}
 
   /// \brief Lower the internal confidence level to Level, but do not raise it.
   void lowerTo(RiskLevel Level) {
@@ -62,25 +61,25 @@
 ///
 /// Given an index variable, recursively crawls a for loop to discover if the
 /// index variable is used in a way consistent with range-based for loop access.
-class ForLoopIndexUseVisitor
-    : public RecursiveASTVisitor<ForLoopIndexUseVisitor> {
- public:
+class ForLoopIndexUseVisitor :
+    public RecursiveASTVisitor<ForLoopIndexUseVisitor> {
+public:
   ForLoopIndexUseVisitor(ASTContext *Context, const VarDecl *IndexVar,
                          const VarDecl *EndVar, const Expr *ContainerExpr,
                          const Expr *ArrayBoundExpr,
-                         bool ContainerNeedsDereference) :
-    Context(Context), IndexVar(IndexVar), EndVar(EndVar),
-    ContainerExpr(ContainerExpr), ArrayBoundExpr(ArrayBoundExpr),
-    ContainerNeedsDereference(ContainerNeedsDereference),
-    OnlyUsedAsIndex(true),  AliasDecl(NULL), ConfidenceLevel(RL_Safe),
-    NextStmtParent(NULL), CurrStmtParent(NULL), ReplaceWithAliasUse(false),
-    AliasFromForInit(false) {
-     if (ContainerExpr) {
-       addComponent(ContainerExpr);
-       llvm::FoldingSetNodeID ID;
-       const Expr *E = ContainerExpr->IgnoreParenImpCasts();
-       E->Profile(ID, *Context, true);
-     }
+                         bool ContainerNeedsDereference)
+      : Context(Context), IndexVar(IndexVar), EndVar(EndVar),
+        ContainerExpr(ContainerExpr), ArrayBoundExpr(ArrayBoundExpr),
+        ContainerNeedsDereference(ContainerNeedsDereference),
+        OnlyUsedAsIndex(true), AliasDecl(NULL), ConfidenceLevel(RL_Safe),
+        NextStmtParent(NULL), CurrStmtParent(NULL), ReplaceWithAliasUse(false),
+        AliasFromForInit(false) {
+    if (ContainerExpr) {
+      addComponent(ContainerExpr);
+      llvm::FoldingSetNodeID ID;
+      const Expr *E = ContainerExpr->IgnoreParenImpCasts();
+      E->Profile(ID, *Context, true);
+    }
   }
 
   /// \brief Finds all uses of IndexVar in Body, placing all usages in Usages,
@@ -104,26 +103,23 @@
   void addComponents(const ComponentVector &Components) {
     // FIXME: add sort(on ID)+unique to avoid extra work.
     for (ComponentVector::const_iterator I = Components.begin(),
-                                         E = Components.end(); I != E; ++I)
+                                         E = Components.end();
+         I != E; ++I)
       addComponent(*I);
   }
 
   /// \brief Accessor for Usages.
   const UsageResult &getUsages() const { return Usages; }
 
   /// \brief Get the container indexed by IndexVar, if any.
-  const Expr *getContainerIndexed() const {
-    return ContainerExpr;
-  }
+  const Expr *getContainerIndexed() const { return ContainerExpr; }
 
   /// \brief Returns the statement declaring the variable created as an alias
   /// for the loop element, if any.
   const DeclStmt *getAliasDecl() const { return AliasDecl; }
 
   /// \brief Accessor for ConfidenceLevel.
-  RiskLevel getRiskLevel() const {
-    return ConfidenceLevel.getRiskLevel();
-  }
+  RiskLevel getRiskLevel() const { return ConfidenceLevel.getRiskLevel(); }
 
   /// \brief Indicates if the alias declaration was in a place where it cannot
   /// simply be removed but rather replaced with a use of the alias variable.
@@ -136,7 +132,7 @@
   /// case need to be adjusted.
   bool aliasFromForInit() const { return AliasFromForInit; }
 
- private:
+private:
   /// Typedef used in CRTP functions.
   typedef RecursiveASTVisitor<ForLoopIndexUseVisitor> VisitorBase;
   friend class RecursiveASTVisitor<ForLoopIndexUseVisitor>;
@@ -184,8 +180,8 @@
   ///
   /// If any of these expressions are encountered outside of an acceptable usage
   /// of the loop element, lower our confidence level.
-  llvm::SmallVector<
-      std::pair<const Expr *, llvm::FoldingSetNodeID>, 16> DependentExprs;
+  llvm::SmallVector<std::pair<const Expr *, llvm::FoldingSetNodeID>, 16>
+  DependentExprs;
 
   /// The parent-in-waiting. Will become the real parent once we traverse down
   /// one level in the AST.
@@ -286,7 +282,7 @@
       return NULL;
     E = ConstructExpr->getArg(0);
     if (const MaterializeTemporaryExpr *Temp =
-        dyn_cast<MaterializeTemporaryExpr>(E))
+            dyn_cast<MaterializeTemporaryExpr>(E))
       E = Temp->GetTemporaryExpr();
     return digThroughConstructors(E);
   }
@@ -300,20 +296,22 @@
     return Uop->getOpcode() == UO_Deref ? Uop->getSubExpr() : NULL;
 
   if (const CXXOperatorCallExpr *OpCall = dyn_cast<CXXOperatorCallExpr>(E))
-    return OpCall->getOperator() == OO_Star && OpCall->getNumArgs() == 1 ?
-        OpCall->getArg(0) : NULL;
+    return OpCall->getOperator() == OO_Star && OpCall->getNumArgs() == 1
+               ? OpCall->getArg(0)
+               : NULL;
 
   return NULL;
 }
 
 /// \brief Returns true when the Container contains an Expr equivalent to E.
-template<typename ContainerT>
+template <typename ContainerT>
 static bool containsExpr(ASTContext *Context, const ContainerT *Container,
                          const Expr *E) {
   llvm::FoldingSetNodeID ID;
   E->Profile(ID, *Context, true);
   for (typename ContainerT::const_iterator I = Container->begin(),
-       End = Container->end(); I != End; ++I)
+                                           End = Container->end();
+       I != End; ++I)
     if (ID == I->second)
       return true;
   return false;
@@ -330,8 +328,8 @@
 static bool isIndexInSubscriptExpr(const Expr *IndexExpr,
                                    const VarDecl *IndexVar) {
   const DeclRefExpr *Idx = getDeclRef(IndexExpr);
-  return Idx && Idx->getType()->isIntegerType()
-             && areSameVariable(IndexVar, Idx->getDecl());
+  return Idx && Idx->getType()->isIntegerType() &&
+         areSameVariable(IndexVar, Idx->getDecl());
 }
 
 /// \brief Returns true when the index expression is a declaration reference to
@@ -403,7 +401,7 @@
 static bool isDereferenceOfUop(const UnaryOperator *Uop,
                                const VarDecl *IndexVar) {
   return Uop->getOpcode() == UO_Deref &&
-      exprReferencesVariable(IndexVar, Uop->getSubExpr());
+         exprReferencesVariable(IndexVar, Uop->getSubExpr());
 }
 
 /// \brief Determines whether the given Decl defines a variable initialized to
@@ -446,10 +444,10 @@
     return isDereferenceOfUop(cast<UnaryOperator>(Init), IndexVar);
 
   case Stmt::CXXOperatorCallExprClass: {
-      const CXXOperatorCallExpr *OpCall = cast<CXXOperatorCallExpr>(Init);
-      if (OpCall->getOperator() == OO_Star)
-        return isDereferenceOfOpCall(OpCall, IndexVar);
-      break;
+    const CXXOperatorCallExpr *OpCall = cast<CXXOperatorCallExpr>(Init);
+    if (OpCall->getOperator() == OO_Star)
+      return isDereferenceOfOpCall(OpCall, IndexVar);
+    break;
   }
 
   default:
@@ -477,7 +475,7 @@
   if (!ConditionExpr || ConditionExpr->isValueDependent())
     return false;
   const ConstantArrayType *ConstType =
-    Context->getAsConstantArrayType(ArrayType);
+      Context->getAsConstantArrayType(ArrayType);
   if (!ConstType)
     return false;
   llvm::APSInt ConditionSize;
@@ -540,15 +538,15 @@
   const Expr *ResultExpr = Member;
   QualType ExprType;
   if (const CXXOperatorCallExpr *Call =
-      dyn_cast<CXXOperatorCallExpr>(Base->IgnoreParenImpCasts())) {
+          dyn_cast<CXXOperatorCallExpr>(Base->IgnoreParenImpCasts())) {
     // If operator->() is a MemberExpr containing a CXXOperatorCallExpr, then
     // the MemberExpr does not have the expression we want. We therefore catch
     // that instance here.
     // For example, if vector<Foo>::iterator defines operator->(), then the
     // example `i->bar()` at the top of this function is a CXXMemberCallExpr
     // referring to `i->` as the member function called. We want just `i`, so
     // we take the argument to operator->() as the base object.
-    if(Call->getOperator() == OO_Arrow) {
+    if (Call->getOperator() == OO_Arrow) {
       assert(Call->getNumArgs() == 1 &&
              "Operator-> takes more than one argument");
       Obj = getDeclRef(Call->getArg(0));
@@ -564,14 +562,13 @@
     assert(ExprType->isPointerType() && "Operator-> returned non-pointer type");
     // FIXME: This works around not having the location of the arrow operator.
     // Consider adding OperatorLoc to MemberExpr?
-    SourceLocation ArrowLoc =
-        Lexer::getLocForEndOfToken(Base->getExprLoc(), 0,
-                                   Context->getSourceManager(),
-                                   Context->getLangOpts());
+    SourceLocation ArrowLoc = Lexer::getLocForEndOfToken(
+        Base->getExprLoc(), 0, Context->getSourceManager(),
+        Context->getLangOpts());
     // If something complicated is happening (i.e. the next token isn't an
     // arrow), give up on making this work.
     if (!ArrowLoc.isInvalid()) {
-      Usages.push_back(Usage(ResultExpr, /*IsArrow=*/true,
+      Usages.push_back(Usage(ResultExpr, /*IsArrow=*/ true,
                              SourceRange(Base->getExprLoc(), ArrowLoc)));
       return true;
     }
@@ -676,16 +673,15 @@
 /// \endcode
 /// and further checking needs to be done later to ensure that exactly one array
 /// is referenced.
-bool ForLoopIndexUseVisitor::TraverseArraySubscriptExpr(
-    ArraySubscriptExpr *E) {
+bool ForLoopIndexUseVisitor::TraverseArraySubscriptExpr(ArraySubscriptExpr *E) {
   Expr *Arr = E->getBase();
   if (!isIndexInSubscriptExpr(E->getIdx(), IndexVar))
     return VisitorBase::TraverseArraySubscriptExpr(E);
 
   if ((ContainerExpr && !areSameExpr(Context, Arr->IgnoreParenImpCasts(),
-                                     ContainerExpr->IgnoreParenImpCasts()))
-      || !arrayMatchesBoundExpr(Context, Arr->IgnoreImpCasts()->getType(),
-                                ArrayBoundExpr)) {
+                                     ContainerExpr->IgnoreParenImpCasts())) ||
+      !arrayMatchesBoundExpr(Context, Arr->IgnoreImpCasts()->getType(),
+                             ArrayBoundExpr)) {
     // If we have already discovered the array being indexed and this isn't it
     // or this array doesn't match, mark this loop as unconvertible.
     OnlyUsedAsIndex = false;
@@ -752,8 +748,7 @@
       isAliasDecl(S->getSingleDecl(), IndexVar)) {
     AliasDecl = S;
     if (CurrStmtParent) {
-      if (isa<IfStmt>(CurrStmtParent) ||
-          isa<WhileStmt>(CurrStmtParent) ||
+      if (isa<IfStmt>(CurrStmtParent) || isa<WhileStmt>(CurrStmtParent) ||
           isa<SwitchStmt>(CurrStmtParent))
         ReplaceWithAliasUse = true;
       else if (isa<ForStmt>(CurrStmtParent)) {
@@ -781,17 +776,14 @@
 }
 
 //// \brief Apply the source transformations necessary to migrate the loop!
-void LoopFixer::doConversion(ASTContext *Context,
-                             const VarDecl *IndexVar,
+void LoopFixer::doConversion(ASTContext *Context, const VarDecl *IndexVar,
                              const VarDecl *MaybeContainer,
                              StringRef ContainerString,
                              const UsageResult &Usages,
-                             const DeclStmt *AliasDecl,
-                             bool AliasUseRequired,
-                             bool AliasFromForInit,
-                             const ForStmt *TheLoop,
-                             bool ContainerNeedsDereference,
-                             bool DerefByValue) {
+                             const DeclStmt *AliasDecl, bool AliasUseRequired,
+                             bool AliasFromForInit, const ForStmt *TheLoop,
+                             bool ContainerNeedsDereference, bool DerefByValue,
+                             bool DerefByConstRef) {
   std::string VarName;
   bool VarNameFromAlias = Usages.size() == 1 && AliasDecl;
   bool AliasVarIsRef = false;
@@ -830,8 +822,7 @@
       ReplacedVarRanges->insert(std::make_pair(TheLoop, IndexVar));
       Replace->insert(
           Replacement(Context->getSourceManager(),
-                      CharSourceRange::getTokenRange(I->Range),
-                      ReplaceText));
+                      CharSourceRange::getTokenRange(I->Range), ReplaceText));
     }
   }
 
@@ -849,17 +840,20 @@
     // to 'T&&'.
     if (DerefByValue)
       AutoRefType = Context->getRValueReferenceType(AutoRefType);
-    else
+    else {
+      if (DerefByConstRef)
+        AutoRefType = Context->getConstType(AutoRefType);
       AutoRefType = Context->getLValueReferenceType(AutoRefType);
+    }
   }
 
   std::string MaybeDereference = ContainerNeedsDereference ? "*" : "";
   std::string TypeString = AutoRefType.getAsString();
-  std::string Range = ("(" + TypeString + " " + VarName + " : "
-                           + MaybeDereference + ContainerString + ")").str();
-  Replace->insert(Replacement(Context->getSourceManager(),
-                              CharSourceRange::getTokenRange(ParenRange),
-                              Range));
+  std::string Range = ("(" + TypeString + " " + VarName + " : " +
+                       MaybeDereference + ContainerString + ")").str();
+  Replace->insert(
+      Replacement(Context->getSourceManager(),
+                  CharSourceRange::getTokenRange(ParenRange), Range));
   GeneratedDecls->insert(make_pair(TheLoop, VarName));
 }
 
@@ -874,7 +868,7 @@
   const CXXMemberCallExpr *TheCall =
       dyn_cast_or_null<CXXMemberCallExpr>(digThroughConstructors(Init));
   if (!TheCall || TheCall->getNumArgs() != 0)
-      return NULL;
+    return NULL;
 
   const MemberExpr *Member = dyn_cast<MemberExpr>(TheCall->getCallee());
   if (!Member)
@@ -905,12 +899,12 @@
   bool BeginIsArrow = false;
   bool EndIsArrow = false;
   const Expr *BeginContainerExpr =
-      getContainerFromBeginEndCall(BeginExpr, /*IsBegin=*/true, &BeginIsArrow);
+      getContainerFromBeginEndCall(BeginExpr, /*IsBegin=*/ true, &BeginIsArrow);
   if (!BeginContainerExpr)
-      return NULL;
+    return NULL;
 
   const Expr *EndContainerExpr =
-      getContainerFromBeginEndCall(EndExpr, /*IsBegin=*/false, &EndIsArrow);
+      getContainerFromBeginEndCall(EndExpr, /*IsBegin=*/ false, &EndIsArrow);
   // Disallow loops that try evil things like this (note the dot and arrow):
   //  for (IteratorType It = Obj.begin(), E = Obj->end(); It != E; ++It) { }
   if (!EndContainerExpr || BeginIsArrow != EndIsArrow ||
@@ -937,10 +931,9 @@
   ParentFinder->gatherAncestors(Context->getTranslationUnitDecl());
   // Ensure that we do not try to move an expression dependent on a local
   // variable declared inside the loop outside of it!
-  DependencyFinderASTVisitor
-      DependencyFinder(&ParentFinder->getStmtToParentStmtMap(),
-                       &ParentFinder->getDeclToParentStmtMap(),
-                       ReplacedVarRanges, TheLoop);
+  DependencyFinderASTVisitor DependencyFinder(
+      &ParentFinder->getStmtToParentStmtMap(),
+      &ParentFinder->getDeclToParentStmtMap(), ReplacedVarRanges, TheLoop);
 
   // Not all of these are actually deferred changes.
   // FIXME: Determine when the external dependency isn't an expression converted
@@ -958,9 +951,9 @@
   if (isa<CXXThisExpr>(ContainerExpr->IgnoreParenImpCasts())) {
     ContainerString = "this";
   } else {
-    ContainerString = getStringFromRange(Context->getSourceManager(),
-                                         Context->getLangOpts(),
-                                         ContainerExpr->getSourceRange());
+    ContainerString =
+        getStringFromRange(Context->getSourceManager(), Context->getLangOpts(),
+                           ContainerExpr->getSourceRange());
   }
 
   // In case someone is using an evil macro, reject this change.
@@ -972,15 +965,11 @@
 /// \brief Given that we have verified that the loop's header appears to be
 /// convertible, run the complete analysis on the loop to determine if the
 /// loop's body is convertible.
-void LoopFixer::findAndVerifyUsages(ASTContext *Context,
-                                    const VarDecl *LoopVar,
-                                    const VarDecl *EndVar,
-                                    const Expr *ContainerExpr,
-                                    const Expr *BoundExpr,
-                                    bool ContainerNeedsDereference,
-                                    bool DerefByValue,
-                                    const ForStmt *TheLoop,
-                                    Confidence ConfidenceLevel) {
+void LoopFixer::findAndVerifyUsages(
+    ASTContext *Context, const VarDecl *LoopVar, const VarDecl *EndVar,
+    const Expr *ContainerExpr, const Expr *BoundExpr,
+    bool ContainerNeedsDereference, bool DerefByValue, bool DerefByConstRef,
+    const ForStmt *TheLoop, Confidence ConfidenceLevel) {
   ForLoopIndexUseVisitor Finder(Context, LoopVar, EndVar, ContainerExpr,
                                 BoundExpr, ContainerNeedsDereference);
   if (ContainerExpr) {
@@ -1004,16 +993,15 @@
       ConfidenceLevel.lowerTo(RL_Risky);
   }
 
-  std::string ContainerString =
-      checkDeferralsAndRejections(Context, ContainerExpr,
-                                  ConfidenceLevel, TheLoop);
+  std::string ContainerString = checkDeferralsAndRejections(
+      Context, ContainerExpr, ConfidenceLevel, TheLoop);
   if (ContainerString.empty())
     return;
 
   doConversion(Context, LoopVar, getReferencedVariable(ContainerExpr),
                ContainerString, Finder.getUsages(), Finder.getAliasDecl(),
                Finder.aliasUseRequired(), Finder.aliasFromForInit(), TheLoop,
-               ContainerNeedsDereference, DerefByValue);
+               ContainerNeedsDereference, DerefByValue, DerefByConstRef);
   ++*AcceptedChanges;
 }
 
@@ -1034,6 +1022,7 @@
   const VarDecl *InitVar = Nodes.getDeclAs<VarDecl>(InitVarName);
   if (!areSameVariable(LoopVar, CondVar) || !areSameVariable(LoopVar, InitVar))
     return;
+
   const VarDecl *EndVar = Nodes.getDeclAs<VarDecl>(EndVarName);
   const VarDecl *ConditionEndVar =
       Nodes.getDeclAs<VarDecl>(ConditionEndVarName);
@@ -1051,14 +1040,64 @@
     ConfidenceLevel.lowerTo(RL_Reasonable);
 
   const Expr *ContainerExpr = NULL;
+  bool DerefByValue = false;
+  bool DerefByConstRef = false;
   bool ContainerNeedsDereference = false;
   // FIXME: Try to put most of this logic inside a matcher. Currently, matchers
   // don't allow the right-recursive checks in digThroughConstructors.
-  if (FixerKind == LFK_Iterator)
+  if (FixerKind == LFK_Iterator) {
     ContainerExpr = findContainer(Context, LoopVar->getInit(),
                                   EndVar ? EndVar->getInit() : EndCall,
                                   &ContainerNeedsDereference);
-  else if (FixerKind == LFK_PseudoArray) {
+
+    QualType InitVarType = InitVar->getType();
+    QualType CanonicalInitVarType = InitVarType.getCanonicalType();
+
+    const CXXMemberCallExpr *BeginCall =
+        Nodes.getNodeAs<CXXMemberCallExpr>(BeginCallName);
+    assert(BeginCall != 0 && "Bad Callback. No begin call expression.");
+    QualType CanonicalBeginType =
+        BeginCall->getMethodDecl()->getResultType().getCanonicalType();
+
+    if (CanonicalBeginType->isPointerType() &&
+        CanonicalInitVarType->isPointerType()) {
+      QualType BeginPointeeType = CanonicalBeginType->getPointeeType();
+      QualType InitPointeeType = CanonicalInitVarType->getPointeeType();
+      // If the initializer and the variable are both pointers check if the
+      // un-qualified pointee types match otherwise we don't use auto.
+      if (!Context->hasSameUnqualifiedType(InitPointeeType, BeginPointeeType))
+        return;
+    } else {
+      // Check for qualified types to avoid conversions from non-const to const
+      // iterator types.
+      if (!Context->hasSameType(CanonicalInitVarType, CanonicalBeginType))
+        return;
+    }
+
+    DerefByValue = Nodes.getNodeAs<QualType>(DerefByValueResultName) != 0;
+    if (!DerefByValue) {
+      if (const QualType *DerefType =
+              Nodes.getNodeAs<QualType>(DerefByRefResultName)) {
+        // A node will only be bound with DerefByRefResultName if we're dealing
+        // with a user-defined iterator type. Test the const qualification of
+        // the reference type.
+        DerefByConstRef = (*DerefType)->getAs<ReferenceType>()->getPointeeType()
+            .isConstQualified();
+      } else {
+        // By nature of the matcher this case is triggered only for built-in
+        // iterator types (i.e. pointers). Test for const qualification of the
+        // pointed-at type.
+        QualType InitPointeeType = CanonicalInitVarType->getPointeeType();
+        assert(isa<PointerType>(CanonicalInitVarType) &&
+               "Non-class iterator type is not a pointer type");
+        DerefByConstRef = InitPointeeType.isConstQualified();
+      }
+    } else {
+      // If the de-referece operator return by value then test for the canonical
+      // const qualification of the init variable type.
+      DerefByConstRef = CanonicalInitVarType.isConstQualified();
+    }
+  } else if (FixerKind == LFK_PseudoArray) {
     if (!EndCall)
       return;
     ContainerExpr = EndCall->getImplicitObjectArgument();
@@ -1071,9 +1110,7 @@
   if (!ContainerExpr && !BoundExpr)
     return;
 
-  bool DerefByValue = Nodes.getNodeAs<QualType>(DerefByValueResultName) != 0;
-
   findAndVerifyUsages(Context, LoopVar, EndVar, ContainerExpr, BoundExpr,
-                      ContainerNeedsDereference, DerefByValue, TheLoop,
-                      ConfidenceLevel);
+                      ContainerNeedsDereference, DerefByValue, DerefByConstRef,
+                      TheLoop, ConfidenceLevel);
 }
Index: cpp11-migrate/LoopConvert/LoopActions.h
===================================================================
--- cpp11-migrate/LoopConvert/LoopActions.h
+++ cpp11-migrate/LoopConvert/LoopActions.h
@@ -77,7 +77,8 @@
                     bool AliasFromForInit,
                     const clang::ForStmt *TheLoop,
                     bool ContainerNeedsDereference,
-                    bool DerefByValue);
+                    bool DerefByValue,
+                    bool DerefByConstRef);
 
   /// \brief Given a loop header that would be convertible, discover all usages
   /// of the index variable and convert the loop if possible.
@@ -88,6 +89,7 @@
                            const clang::Expr *BoundExpr,
                            bool ContainerNeedsDereference,
                            bool DerefByValue,
+                           bool DerefByConstRef,
                            const clang::ForStmt *TheLoop,
                            Confidence ConfidenceLevel);
 
Index: cpp11-migrate/LoopConvert/LoopMatchers.cpp
===================================================================
--- cpp11-migrate/LoopConvert/LoopMatchers.cpp
+++ cpp11-migrate/LoopConvert/LoopMatchers.cpp
@@ -22,10 +22,12 @@
 const char ConditionVarName[] = "conditionVar";
 const char IncrementVarName[] = "incrementVar";
 const char InitVarName[] = "initVar";
+const char BeginCallName[] = "beginCall";
 const char EndCallName[] = "endCall";
 const char ConditionEndVarName[] = "conditionEndVar";
 const char EndVarName[] = "endVar";
 const char DerefByValueResultName[] = "derefByValueResult";
+const char DerefByRefResultName[] = "derefByRefResult";
 
 // shared matchers
 static const TypeMatcher AnyType = anything();
@@ -109,10 +111,23 @@
 ///   - If the end iterator variable 'g' is defined, it is the same as 'f'
 StatementMatcher makeIteratorLoopMatcher() {
   StatementMatcher BeginCallMatcher =
-      memberCallExpr(argumentCountIs(0), callee(methodDecl(hasName("begin"))));
+      memberCallExpr(
+        argumentCountIs(0),
+        callee(
+          methodDecl(hasName("begin"))
+        )
+      ).bind(BeginCallName);
 
   DeclarationMatcher InitDeclMatcher =
-      varDecl(hasInitializer(anything())).bind(InitVarName);
+      varDecl(
+        hasInitializer(
+          anyOf(
+            ignoringParenImpCasts(BeginCallMatcher),
+            materializeTemporaryExpr(ignoringParenImpCasts(BeginCallMatcher)),
+            hasDescendant(BeginCallMatcher)
+          )
+        )
+      ).bind(InitVarName);
 
   DeclarationMatcher EndDeclMatcher =
       varDecl(hasInitializer(anything())).bind(EndVarName);
@@ -157,14 +172,19 @@
                 returns(
                   // Skip loops where the iterator's operator* returns an
                   // rvalue reference. This is just weird.
-                  qualType(unless(hasCanonicalType(rValueReferenceType())))
+                  qualType(
+                    unless(
+                      hasCanonicalType(rValueReferenceType())
+                    )
+                  ).bind(DerefByRefResultName)
                 )
               )
             )
           )
         )
       );
 
+
   return
     forStmt(
       hasLoopInit(anyOf(
Index: cpp11-migrate/LoopConvert/LoopMatchers.h
===================================================================
--- cpp11-migrate/LoopConvert/LoopMatchers.h
+++ cpp11-migrate/LoopConvert/LoopMatchers.h
@@ -27,10 +27,12 @@
 extern const char ConditionEndVarName[];
 extern const char IncrementVarName[];
 extern const char InitVarName[];
+extern const char BeginCallName[];
 extern const char EndExprName[];
 extern const char EndCallName[];
 extern const char EndVarName[];
 extern const char DerefByValueResultName[];
+extern const char DerefByRefResultName[];
 
 clang::ast_matchers::StatementMatcher makeArrayLoopMatcher();
 clang::ast_matchers::StatementMatcher makeIteratorLoopMatcher();
Index: test/cpp11-migrate/LoopConvert/Inputs/structures.h
===================================================================
--- test/cpp11-migrate/LoopConvert/Inputs/structures.h
+++ test/cpp11-migrate/LoopConvert/Inputs/structures.h
@@ -131,10 +131,13 @@
 template<typename IteratorType>
 struct Nested {
   typedef IteratorType* iterator;
+  typedef const IteratorType* const_iterator;
   IteratorType *operator->();
   IteratorType operator*();
   iterator begin();
   iterator end();
+  const_iterator begin() const;
+  const_iterator end() const;
 };
 
 // Like llvm::SmallPtrSet, the iterator has a dereference operator that returns
Index: test/cpp11-migrate/LoopConvert/iterator.cpp
===================================================================
--- test/cpp11-migrate/LoopConvert/iterator.cpp
+++ test/cpp11-migrate/LoopConvert/iterator.cpp
@@ -26,20 +26,20 @@
   for (S::const_iterator it = s.begin(), e = s.end(); it != e; ++it) {
     printf("s has value %d\n", (*it).x);
   }
-  // CHECK: for (auto & elem : s)
+  // CHECK: for (auto const & elem : s)
   // CHECK-NEXT: printf("s has value %d\n", (elem).x);
 
   S *ps;
   for (S::const_iterator it = ps->begin(), e = ps->end(); it != e; ++it) {
     printf("s has value %d\n", (*it).x);
   }
-  // CHECK: for (auto & p : *ps)
+  // CHECK: for (auto const & p : *ps)
   // CHECK-NEXT: printf("s has value %d\n", (p).x);
 
   for (S::const_iterator it = s.begin(), e = s.end(); it != e; ++it) {
     printf("s has value %d\n", it->x);
   }
-  // CHECK: for (auto & elem : s)
+  // CHECK: for (auto const & elem : s)
   // CHECK-NEXT: printf("s has value %d\n", elem.x);
 
   for (S::iterator it = s.begin(), e = s.end(); it != e; ++it) {
@@ -84,15 +84,17 @@
        it != e; ++it) {
     printf("Fibonacci number is %d\n", *it);
   }
-  // CHECK: for (auto & elem : v)
-  // CHECK-NEXT: printf("Fibonacci number is %d\n", elem);
+  // CHECK: for (dependent<int>::const_iterator it = v.begin(), e = v.end();
+  // CHECK-NEXT: it != e; ++it) {
+  // CHECK-NEXT: printf("Fibonacci number is %d\n", *it);
 
   for (dependent<int>::const_iterator it(v.begin()), e = v.end();
        it != e; ++it) {
     printf("Fibonacci number is %d\n", *it);
   }
-  // CHECK: for (auto & elem : v)
-  // CHECK-NEXT: printf("Fibonacci number is %d\n", elem);
+  // CHECK: for (dependent<int>::const_iterator it(v.begin()), e = v.end();
+  // CHECK-NEXT: it != e; ++it) {
+  // CHECK-NEXT: printf("Fibonacci number is %d\n", *it);
 
   doublyDependent<int,int> intmap;
   for (doublyDependent<int,int>::iterator it = intmap.begin(), e = intmap.end();
@@ -174,14 +176,14 @@
 
   void doLoop() const {
     for (const_iterator I = begin(), E = end(); I != E; ++I) {
-      // CHECK: for (auto & elem : *this) {
+      // CHECK: for (auto const & elem : *this) {
     }
     for (const_iterator I = C::begin(), E = C::end(); I != E; ++I) {
-      // CHECK: for (auto & elem : *this) {
+      // CHECK: for (auto const & elem : *this) {
     }
     for (const_iterator I = begin(), E = end(); I != E; ++I) {
       // CHECK: for (const_iterator I = begin(), E = end(); I != E; ++I) {
-      // RISKY: for (auto & elem : *this) {
+      // RISKY: for (auto const & elem : *this) {
       doSomething();
     }
   }
@@ -201,4 +203,4 @@
       // CHECK: for (auto & elem : *this) {
     }
   }
-};
+};
\ No newline at end of file
Index: test/cpp11-migrate/LoopConvert/naming-conflict.cpp
===================================================================
--- test/cpp11-migrate/LoopConvert/naming-conflict.cpp
+++ test/cpp11-migrate/LoopConvert/naming-conflict.cpp
@@ -36,7 +36,7 @@
     printf("s has value %d\n", (*it).x);
     printf("Max of 3 and 5: %d\n", MAX(3,5));
   }
-  // CHECK: for (auto & MAXs_it : MAXs)
+  // CHECK: for (auto const & MAXs_it : MAXs)
   // CHECK-NEXT: printf("s has value %d\n", (MAXs_it).x);
   // CHECK-NEXT: printf("Max of 3 and 5: %d\n", MAX(3,5));
 
Index: test/cpp11-migrate/LoopConvert/nesting.cpp
===================================================================
--- test/cpp11-migrate/LoopConvert/nesting.cpp
+++ test/cpp11-migrate/LoopConvert/nesting.cpp
@@ -54,4 +54,16 @@
   // CHECK: for (auto & elem : NestT) {
   // CHECK-NEXT: for (T::iterator TI = (elem).begin(), TE = (elem).end(); TI != TE; ++TI) {
   // CHECK-NEXT: printf("%d", *TI);
+
+  Nested<S> NestS;
+  for (Nested<S>::const_iterator I = NestS.begin(), E = NestS.end(); I != E; ++I) {
+    for (S::const_iterator SI = (*I).begin(), SE = (*I).end(); SI != SE; ++SI) {
+      printf("%d", *SI);
+    }
+  }
+  // The inner loop is also convertible, but doesn't need to be converted
+  // immediately. Update this test when that changes!
+  // CHECK: for (auto const & elem : NestS) {
+  // CHECK-NEXT: for (S::const_iterator SI = (elem).begin(), SE = (elem).end(); SI != SE; ++SI) {
+  // CHECK-NEXT: printf("%d", *SI);
 }
Index: test/cpp11-migrate/LoopConvert/single-iterator.cpp
===================================================================
--- test/cpp11-migrate/LoopConvert/single-iterator.cpp
+++ test/cpp11-migrate/LoopConvert/single-iterator.cpp
@@ -37,20 +37,20 @@
   for (S::const_iterator it = s.begin(); it != s.end(); ++it) {
     printf("s has value %d\n", (*it).x);
   }
-  // CHECK: for (auto & elem : s)
+  // CHECK: for (auto const & elem : s)
   // CHECK-NEXT: printf("s has value %d\n", (elem).x);
 
   S *ps;
   for (S::const_iterator it = ps->begin(); it != ps->end(); ++it) {
     printf("s has value %d\n", (*it).x);
   }
-  // CHECK: for (auto & p : *ps)
+  // CHECK: for (auto const & p : *ps)
   // CHECK-NEXT: printf("s has value %d\n", (p).x);
 
   for (S::const_iterator it = s.begin(); it != s.end(); ++it) {
     printf("s has value %d\n", it->x);
   }
-  // CHECK: for (auto & elem : s)
+  // CHECK: for (auto const & elem : s)
   // CHECK-NEXT: printf("s has value %d\n", elem.x);
 
   for (S::iterator it = s.begin(); it != s.end(); ++it) {
@@ -95,21 +95,23 @@
        it != v.end(); ++it) {
     printf("Fibonacci number is %d\n", *it);
   }
-  // CHECK: for (auto & elem : v)
-  // CHECK-NEXT: printf("Fibonacci number is %d\n", elem);
+  // CHECK: for (dependent<int>::const_iterator it = v.begin();
+  // CHECK-NEXT: it != v.end(); ++it) {
+  // CHECK-NEXT: printf("Fibonacci number is %d\n", *it);
 
   for (dependent<int>::const_iterator it(v.begin());
        it != v.end(); ++it) {
     printf("Fibonacci number is %d\n", *it);
   }
-  // CHECK: for (auto & elem : v)
-  // CHECK-NEXT: printf("Fibonacci number is %d\n", elem);
+  // CHECK: for (dependent<int>::const_iterator it(v.begin());
+  // CHECK-NEXT: it != v.end(); ++it) {
+  // CHECK-NEXT: printf("Fibonacci number is %d\n", *it);
 
   doublyDependent<int,int> intmap;
   for (doublyDependent<int,int>::iterator it = intmap.begin();
        it != intmap.end(); ++it) {
     printf("intmap[%d] = %d", it->first, it->second);
   }
   // CHECK: for (auto & elem : intmap)
   // CHECK-NEXT: printf("intmap[%d] = %d", elem.first, elem.second);
-}
+}
\ No newline at end of file
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to