Fix loop-convert for trivially copyable types.

Previously, we would rewrite:
void f(const vector<int> &v) {
  for (size_t i = 0; i < v.size(); ++i) {
to
  for (const auto &elem : v) {

Now we rewrite it to:
  for (auto elem : v) {
(and similarly for iterator based loops).

llvm-svn: 248438
diff --git a/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp b/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
index 054e5ce..774ecbb 100644
--- a/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
@@ -500,7 +500,10 @@
   // If the new variable name is from the aliased variable, then the reference
   // type for the new variable should only be used if the aliased variable was
   // declared as a reference.
-  if (!VarNameFromAlias || AliasVarIsRef) {
+  bool UseCopy = (VarNameFromAlias && !AliasVarIsRef) ||
+                 (Descriptor.DerefByConstRef && Descriptor.IsTriviallyCopyable);
+
+  if (!UseCopy) {
     if (Descriptor.DerefByConstRef) {
       AutoType =
           Context->getLValueReferenceType(Context->getConstType(AutoType));
@@ -547,35 +550,29 @@
                                               RangeDescriptor &Descriptor) {
   // On arrays and pseudoarrays, we must figure out the qualifiers from the
   // usages.
-  if (usagesAreConst(Usages)) {
+  if (usagesAreConst(Usages) ||
+      containerIsConst(ContainerExpr, Descriptor.ContainerNeedsDereference)) {
     Descriptor.DerefByConstRef = true;
-  } else {
-    if (usagesReturnRValues(Usages)) {
-      // If the index usages (dereference, subscript, at, ...) return rvalues,
-      // then we should not use a reference, because we need to keep the code
-      // correct if it mutates the returned objects.
-      Descriptor.DerefByValue = true;
-      // Try to find the type of the elements on the container, to check if
-      // they are trivially copyable.
-      for (const Usage &U : Usages) {
-        if (!U.Expression || U.Expression->getType().isNull())
-          continue;
-        QualType Type = U.Expression->getType().getCanonicalType();
-        if (U.Kind == Usage::UK_MemberThroughArrow) {
-          if (!Type->isPointerType())
-            continue;
-          Type = Type->getPointeeType();
-        }
-        Descriptor.IsTriviallyCopyable = Type.isTriviallyCopyableType(*Context);
-        break;
+  }
+  if (usagesReturnRValues(Usages)) {
+    // If the index usages (dereference, subscript, at, ...) return rvalues,
+    // then we should not use a reference, because we need to keep the code
+    // correct if it mutates the returned objects.
+    Descriptor.DerefByValue = true;
+  }
+  // Try to find the type of the elements on the container, to check if
+  // they are trivially copyable.
+  for (const Usage &U : Usages) {
+    if (!U.Expression || U.Expression->getType().isNull())
+      continue;
+    QualType Type = U.Expression->getType().getCanonicalType();
+    if (U.Kind == Usage::UK_MemberThroughArrow) {
+      if (!Type->isPointerType()) {
+        continue;
       }
-    } else if (containerIsConst(ContainerExpr,
-                                Descriptor.ContainerNeedsDereference)) {
-      // The usages are lvalue references, we add a 'const' if the container
-      // is 'const'. This will always be the case with const arrays (unless
-      // usagesAreConst() returned true).
-      Descriptor.DerefByConstRef = true;
+      Type = Type->getPointeeType();
     }
+    Descriptor.IsTriviallyCopyable = Type.isTriviallyCopyableType(*Context);
   }
 }
 
@@ -604,10 +601,11 @@
       // 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.
-      Descriptor.DerefByConstRef = (*DerefType)
-                                       ->getAs<ReferenceType>()
-                                       ->getPointeeType()
-                                       .isConstQualified();
+      auto ValueType = (*DerefType)->getAs<ReferenceType>()->getPointeeType();
+
+      Descriptor.DerefByConstRef = ValueType.isConstQualified();
+      Descriptor.IsTriviallyCopyable =
+          ValueType.isTriviallyCopyableType(*Context);
     } else {
       // By nature of the matcher this case is triggered only for built-in
       // iterator types (i.e. pointers).
@@ -617,6 +615,9 @@
       // We test for const qualification of the pointed-at type.
       Descriptor.DerefByConstRef =
           CanonicalInitVarType->getPointeeType().isConstQualified();
+      Descriptor.IsTriviallyCopyable =
+          CanonicalInitVarType->getPointeeType().isTriviallyCopyableType(
+              *Context);
     }
   }
 }