Changed MemberPointerTypeLoc to PointerTypeLoc and removed the logic for 
removing stars.

Hi revane,

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

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D839?vs=2095&id=2097#toc

Files:
  cpp11-migrate/UseAuto/UseAutoActions.cpp
  cpp11-migrate/UseAuto/UseAutoMatchers.cpp
  cpp11-migrate/UseAuto/UseAutoMatchers.h
  test/cpp11-migrate/UseAuto/new.cpp
Index: cpp11-migrate/UseAuto/UseAutoActions.cpp
===================================================================
--- cpp11-migrate/UseAuto/UseAutoActions.cpp
+++ cpp11-migrate/UseAuto/UseAutoActions.cpp
@@ -20,7 +20,6 @@
 using namespace clang::tooling;
 using namespace clang;
 
-
 void IteratorReplacer::run(const MatchFinder::MatchResult &Result) {
   const DeclStmt *D = Result.Nodes.getNodeAs<DeclStmt>(IteratorDeclStmtId);
   assert(D && "Bad Callback. No node provided");
@@ -49,15 +48,17 @@
     const Expr *E = Construct->arg_begin()->IgnoreParenImpCasts();
     if (E != E->IgnoreConversionOperator())
       // We hit a conversion operator. Early-out now as they imply an implicit
-      // conversion from a different type. Could also mean an explicit conversion
+      // conversion from a different type. Could also mean an explicit
+      // conversion
       // from the same type but that's pretty rare.
       return;
 
     if (const CXXConstructExpr *NestedConstruct = dyn_cast<CXXConstructExpr>(E))
       // If we ran into an implicit conversion constructor, can't convert.
       //
       // FIXME: The following only checks if the constructor can be used
-      // implicitly, not if it actually was. Cases where the converting constructor
+      // implicitly, not if it actually was. Cases where the converting
+      // constructor
       // was used explicitly won't get converted.
       if (NestedConstruct->getConstructor()->isConvertingConstructor(false))
         return;
@@ -78,46 +79,59 @@
 }
 
 void NewReplacer::run(const MatchFinder::MatchResult &Result) {
-  const VarDecl *D = Result.Nodes.getNodeAs<VarDecl>(DeclWithNewId);
+  const DeclStmt *D = Result.Nodes.getNodeAs<DeclStmt>(DeclWithNewId);
   assert(D && "Bad Callback. No node provided");
 
   SourceManager &SM = *Result.SourceManager;
   if (!SM.isFromMainFile(D->getLocStart()))
     return;
 
-  const CXXNewExpr *NewExpr = Result.Nodes.getNodeAs<CXXNewExpr>(NewExprId);
-  assert(NewExpr && "Bad Callback. No CXXNewExpr bound");
-
-  // If declaration and initializer have exactly the same type, just replace
-  // with 'auto'.
-  if (Result.Context->hasSameType(D->getType(), NewExpr->getType())) {
-    TypeLoc TL = D->getTypeSourceInfo()->getTypeLoc();
-    CharSourceRange Range(TL.getSourceRange(), /*IsTokenRange=*/ true);
-    // Space after 'auto' to handle cases where the '*' in the pointer type
-    // is next to the identifier. This avoids changing 'int *p' into 'autop'.
-    Replace.insert(tooling::Replacement(SM, Range, "auto "));
-    ++AcceptedChanges;
-    return;
-  }
+  const VarDecl *FirstDecl = cast<VarDecl>(*D->decl_begin());
+  assert(FirstDecl && "No VarDecl provided");
+  const QualType FirstDeclType = FirstDecl->getType().getCanonicalType();
+  TypeLoc FirsDeclTypeLoc = FirstDecl->getTypeSourceInfo()->getTypeLoc();
 
-  // If the CV qualifiers for the pointer differ then we still use auto, just
-  // need to leave the qualifier behind.
-  if (Result.Context->hasSameUnqualifiedType(D->getType(),
-                                             NewExpr->getType())) {
-    TypeLoc TL = D->getTypeSourceInfo()->getTypeLoc();
-    CharSourceRange Range(TL.getSourceRange(), /*IsTokenRange=*/ true);
-    // Space after 'auto' to handle cases where the '*' in the pointer type
-    // is next to the identifier. This avoids changing 'int *p' into 'autop'.
-    Replace.insert(tooling::Replacement(SM, Range, "auto "));
-    ++AcceptedChanges;
-    return;
-  }
+  unsigned VarDecls = 0;
+  for (clang::DeclStmt::const_decl_iterator DI = D->decl_begin(),
+                                            DE = D->decl_end();
+       DI != DE; ++DI) {
 
-  // The VarDecl and Initializer have mismatching types.
-  return;
+    const VarDecl *V = cast<VarDecl>(*DI);
+    assert(V && "No VarDecl provided");
+
+    const CXXNewExpr *NewExpr =
+        cast<CXXNewExpr>(V->getInit()->IgnoreParenImpCasts());
+    assert(NewExpr && "No CXXNewExpr provided");
 
+    // If VarDecl and Initializer have mismatching unqualified types.
+    if (!Result.Context->hasSameUnqualifiedType(V->getType(),
+                                                NewExpr->getType()))
+      return;
+    // Remove explicitly written '*' from declarations where there's more than
+    // one declaration in the declaration list.
+    if (VarDecls > 0) {
+      // All delcarations should match the same non-decorated type.
+      if (FirstDeclType != V->getType().getCanonicalType())
+        return;
+
+      PointerTypeLoc Q =
+          cast<PointerTypeLoc>(V->getTypeSourceInfo()->getTypeLoc());
+      SourceLocation SL = Q.getStarLoc();
+      while (SL != FirsDeclTypeLoc.getBeginLoc()) {
+        Replace.insert(tooling::Replacement(SM, SL, 1, ""));
+        Q = cast<PointerTypeLoc>(Q.getNextTypeLoc());
+        SL = Q.getStarLoc();
+      }
+    }
+    ++VarDecls;
+  }
   // FIXME: There is, however, one case we can address: when the VarDecl
   // pointee is the same as the initializer, just more CV-qualified. However,
   // TypeLoc information is not reliable where CV qualifiers are concerned so
   // we can't do anything about this case for now.
+  CharSourceRange Range(FirsDeclTypeLoc.getSourceRange(), true);
+  // Space after 'auto' to handle cases where the '*' in the pointer type
+  // is next to the identifier. This avoids changing 'int *p' into 'autop'.
+  Replace.insert(tooling::Replacement(SM, Range, "auto "));
+  ++AcceptedChanges;
 }
Index: cpp11-migrate/UseAuto/UseAutoMatchers.cpp
===================================================================
--- cpp11-migrate/UseAuto/UseAutoMatchers.cpp
+++ cpp11-migrate/UseAuto/UseAutoMatchers.cpp
@@ -258,29 +258,29 @@
   ).bind(IteratorDeclStmtId);
 }
 
-DeclarationMatcher makeDeclWithNewMatcher() {
-  return varDecl(
-           hasInitializer(
-             ignoringParenImpCasts(
-               newExpr().bind(NewExprId)
-             )
-           ),
-
-           // FIXME: TypeLoc information is not reliable where CV qualifiers are
-           // concerned so these types can't be handled for now.
-           unless(hasType(pointerType(pointee(hasLocalQualifiers())))),
+StatementMatcher makeDeclWithNewMatcher() {
+  return declStmt(
+    has(varDecl()),
+    unless(has(varDecl(
+      anyOf(
+        unless(hasInitializer(
+          ignoringParenImpCasts(newExpr())
+        )),
+        // FIXME: TypeLoc information is not reliable where CV qualifiers are
+        // concerned so these types can't be handled for now.
+        hasType(pointerType(pointee(hasCanonicalType(hasLocalQualifiers())))),
 
-           // FIXME: Handle function pointers. For now we ignore them because
-           // the replacement replaces the entire type specifier source range
-           // which includes the identifier.
-           unless(
-             hasType(
-               pointsTo(
-                 pointsTo(
-                   parenType(innerType(functionType()))
-                 )
-               )
-             )
-           )
-         ).bind(DeclWithNewId);
+        // FIXME: Handle function pointers. For now we ignore them because
+        // the replacement replaces the entire type specifier source range
+        // which includes the identifier.
+        hasType(
+          pointsTo(
+            pointsTo(
+              parenType(innerType(functionType()))
+            )
+          )
+        )
+      )
+    )))
+   ).bind(DeclWithNewId);
 }
Index: cpp11-migrate/UseAuto/UseAutoMatchers.h
===================================================================
--- cpp11-migrate/UseAuto/UseAutoMatchers.h
+++ cpp11-migrate/UseAuto/UseAutoMatchers.h
@@ -28,6 +28,6 @@
 
 /// \brief Create a matcher that matches variable declarations that are
 /// initialized by a C++ new expression.
-clang::ast_matchers::DeclarationMatcher makeDeclWithNewMatcher();
+clang::ast_matchers::StatementMatcher makeDeclWithNewMatcher();
 
 #endif // LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_USE_AUTO_MATCHERS_H
Index: test/cpp11-migrate/UseAuto/new.cpp
===================================================================
--- test/cpp11-migrate/UseAuto/new.cpp
+++ test/cpp11-migrate/UseAuto/new.cpp
@@ -49,4 +49,22 @@
 
   MyType *g{new MyType};
   // CHECK: MyType *g{new MyType};
+
+  // Test for declaration lists.
+  {
+    MyType *a = new MyType(), *b = new MyType();
+    // CHECK: auto a = new MyType(), b = new MyType();
+
+    // Non-initialized declaration should not be transformed.
+    MyType *c = new MyType(), *d;
+    // CHECK: MyType *c = new MyType(), *d;
+
+    MyType **e = new MyType*(), **f = new MyType*();
+    // CHECK: auto e = new MyType*(), f = new MyType*();
+
+    // Mismatching types in declaration lists should not be transformed.
+    MyType *g = new MyType(), **h = new MyType*();
+    // CHECK: MyType *g = new MyType(), **h = new MyType*();
+  }
+  return 0;
 }
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to