angelgarcia created this revision.
angelgarcia added a reviewer: klimek.
angelgarcia added subscribers: cfe-commits, alexfh.

Consider a declaration an alias even if it doesn't have the same unqualified 
type than the container element, as long as one can be converted to the other 
using only implicit casts.

http://reviews.llvm.org/D14442

Files:
  clang-tidy/modernize/LoopConvertUtils.cpp
  test/clang-tidy/modernize-loop-convert-extra.cpp

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
@@ -167,6 +167,15 @@
   // 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);
+
   // Ensure that removing the alias doesn't leave empty lines behind.
   for (int I = 0; I < N; ++I) {
     auto &X = IntArr[I];
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<CXXConstructExpr>(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: {


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
@@ -167,6 +167,15 @@
   // 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);
+
   // Ensure that removing the alias doesn't leave empty lines behind.
   for (int I = 0; I < N; ++I) {
     auto &X = IntArr[I];
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<CXXConstructExpr>(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: {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to