- Removing debug code
    - Reflecting change in ASTMatcher name
    - Reviewer-suggested improvements

Hi gribozavr, klimek,

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

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D582?vs=1423&id=1484#toc

Files:
  cpp11-migrate/UseAuto/UseAuto.cpp
  cpp11-migrate/UseAuto/UseAutoActions.cpp
  cpp11-migrate/UseAuto/UseAutoActions.h
  cpp11-migrate/UseAuto/UseAutoMatchers.cpp
  cpp11-migrate/UseAuto/UseAutoMatchers.h
  test/cpp11-migrate/UseAuto/new.cpp
  test/cpp11-migrate/UseAuto/new_cv_failing.cpp
Index: cpp11-migrate/UseAuto/UseAuto.cpp
===================================================================
--- cpp11-migrate/UseAuto/UseAuto.cpp
+++ cpp11-migrate/UseAuto/UseAuto.cpp
@@ -35,9 +35,13 @@
   unsigned AcceptedChanges = 0;
 
   MatchFinder Finder;
-  UseAutoFixer Fixer(UseAutoTool.getReplacements(), AcceptedChanges, MaxRisk);
+  IteratorReplacer ReplaceIterators(UseAutoTool.getReplacements(),
+                                    AcceptedChanges, MaxRisk);
+  NewReplacer ReplaceNew(UseAutoTool.getReplacements(), AcceptedChanges,
+                         MaxRisk);
 
-  Finder.addMatcher(makeIteratorMatcher(), &Fixer);
+  Finder.addMatcher(makeIteratorDeclMatcher(), &ReplaceIterators);
+  Finder.addMatcher(makeDeclWithNewMatcher(), &ReplaceNew);
 
   if (int Result = UseAutoTool.run(newFrontendActionFactory(&Finder))) {
     llvm::errs() << "Error encountered during translation.\n";
Index: cpp11-migrate/UseAuto/UseAutoActions.cpp
===================================================================
--- cpp11-migrate/UseAuto/UseAutoActions.cpp
+++ cpp11-migrate/UseAuto/UseAutoActions.cpp
@@ -8,7 +8,8 @@
 //===----------------------------------------------------------------------===//
 ///
 ///  \file
-///  \brief This file contains the implementation of the UseAutoFixer class.
+///  \brief This file contains the implementation of callbacks for the UseAuto
+///  transform.
 ///
 //===----------------------------------------------------------------------===//
 #include "UseAutoActions.h"
@@ -19,8 +20,8 @@
 using namespace clang::tooling;
 using namespace clang;
 
-void UseAutoFixer::run(const MatchFinder::MatchResult &Result) {
-  const VarDecl *D = Result.Nodes.getNodeAs<VarDecl>(DeclNodeId);
+void IteratorReplacer::run(const MatchFinder::MatchResult &Result) {
+  const VarDecl *D = Result.Nodes.getNodeAs<VarDecl>(IteratorDeclId);
 
   assert(D && "Bad Callback. No node provided");
 
@@ -68,3 +69,48 @@
     ++AcceptedChanges;
   }
 }
+
+void NewReplacer::run(const MatchFinder::MatchResult &Result) {
+  const VarDecl *D = Result.Nodes.getNodeAs<VarDecl>(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;
+  }
+
+  // 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;
+  }
+
+  // The VarDecl and Initializer have mismatching types.
+  return;
+
+  // 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.
+}
Index: cpp11-migrate/UseAuto/UseAutoActions.h
===================================================================
--- cpp11-migrate/UseAuto/UseAutoActions.h
+++ cpp11-migrate/UseAuto/UseAutoActions.h
@@ -8,8 +8,8 @@
 //===----------------------------------------------------------------------===//
 ///
 ///  \file
-///  \brief This file contains the declaration of the UseAutoFixer class which
-///  is used as an ASTMatcher callback.
+///  \brief This file contains the declarations for callbacks used by the
+///  UseAuto transform.
 ///
 //===----------------------------------------------------------------------===//
 #ifndef LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_USE_AUTO_ACTIONS_H
@@ -19,16 +19,37 @@
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/Tooling/Refactoring.h"
 
-/// \brief The callback to be used for use-auto AST matchers.
-class UseAutoFixer : public clang::ast_matchers::MatchFinder::MatchCallback {
+/// \brief The callback to be used when replacing type specifiers of variable
+/// declarations that are iterators.
+class IteratorReplacer
+    : public clang::ast_matchers::MatchFinder::MatchCallback {
 public:
-  UseAutoFixer(clang::tooling::Replacements &Replace, unsigned &AcceptedChanges,
-               RiskLevel)
+  IteratorReplacer(clang::tooling::Replacements &Replace,
+                   unsigned &AcceptedChanges, RiskLevel)
       : Replace(Replace), AcceptedChanges(AcceptedChanges) {
   }
 
   /// \brief Entry point to the callback called when matches are made.
-  virtual void run(const clang::ast_matchers::MatchFinder::MatchResult &Result);
+  virtual void run(const clang::ast_matchers::MatchFinder::MatchResult &Result)
+      LLVM_OVERRIDE;
+
+private:
+  clang::tooling::Replacements &Replace;
+  unsigned &AcceptedChanges;
+};
+
+/// \brief The callback used when replacing type specifiers of variable
+/// declarations initialized by a C++ new expression.
+class NewReplacer : public clang::ast_matchers::MatchFinder::MatchCallback {
+public:
+  NewReplacer(clang::tooling::Replacements &Replace, unsigned &AcceptedChanges,
+              RiskLevel)
+      : Replace(Replace), AcceptedChanges(AcceptedChanges) {
+  }
+
+  /// \brief Entry point to the callback called when matches are made.
+  virtual void run(const clang::ast_matchers::MatchFinder::MatchResult &Result)
+      LLVM_OVERRIDE;
 
 private:
   clang::tooling::Replacements &Replace;
Index: cpp11-migrate/UseAuto/UseAutoMatchers.cpp
===================================================================
--- cpp11-migrate/UseAuto/UseAutoMatchers.cpp
+++ cpp11-migrate/UseAuto/UseAutoMatchers.cpp
@@ -18,7 +18,9 @@
 using namespace clang::ast_matchers;
 using namespace clang;
 
-const char *DeclNodeId = "decl";
+const char *IteratorDeclId = "iterator_decl";
+const char *DeclWithNewId = "decl_new";
+const char *NewExprId = "new_expr";
 
 namespace clang {
 namespace ast_matchers {
@@ -230,7 +232,7 @@
 }
 } // namespace
 
-DeclarationMatcher makeIteratorMatcher() {
+DeclarationMatcher makeIteratorDeclMatcher() {
   return varDecl(allOf(
                    hasWrittenNonListInitializer(),
                    unless(hasType(autoType())),
@@ -243,5 +245,32 @@
                        )
                      )
                    )
-                 )).bind(DeclNodeId);
+                 )).bind(IteratorDeclId);
+}
+
+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())))),
+
+           // 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);
 }
Index: cpp11-migrate/UseAuto/UseAutoMatchers.h
===================================================================
--- cpp11-migrate/UseAuto/UseAutoMatchers.h
+++ cpp11-migrate/UseAuto/UseAutoMatchers.h
@@ -17,11 +17,17 @@
 
 #include "clang/ASTMatchers/ASTMatchers.h"
 
-extern const char *DeclNodeId;
+extern const char *IteratorDeclId;
+extern const char *DeclWithNewId;
+extern const char *NewExprId;
 
 /// \brief Create a matcher that matches variable declarations where the type
 /// is an iterator for an std container and has an explicit initializer of the
 /// same type.
-clang::ast_matchers::DeclarationMatcher makeIteratorMatcher();
+clang::ast_matchers::DeclarationMatcher makeIteratorDeclMatcher();
+
+/// \brief Create a matcher that matches variable declarations that are
+/// initialized by a C++ new expression.
+clang::ast_matchers::DeclarationMatcher makeDeclWithNewMatcher();
 
 #endif // LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_USE_AUTO_MATCHERS_H
Index: test/cpp11-migrate/UseAuto/new.cpp
===================================================================
--- /dev/null
+++ test/cpp11-migrate/UseAuto/new.cpp
@@ -0,0 +1,52 @@
+// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
+// RUN: cpp11-migrate -use-auto %t.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%t.cpp %s
+
+class MyType {
+};
+
+class MyDerivedType : public MyType {
+};
+
+int main(int argc, char **argv) {
+  MyType *a = new MyType();
+  // CHECK: auto a = new MyType();
+
+  static MyType *a_static = new MyType();
+  // CHECK: static auto a_static = new MyType();
+
+  MyType *b = new MyDerivedType();
+  // CHECK: MyType *b = new MyDerivedType();
+
+  void *c = new MyType();
+  // CHECK: void *c = new MyType();
+
+  // CV-qualifier tests.
+  //
+  // NOTE : the form "type const" is expected here because of a deficiency in
+  // TypeLoc where CV qualifiers are not considered part of the type location
+  // info. That is, all that is being replaced in each case is "MyType *" and
+  // not "MyType * const".
+  {
+    static MyType * const d_static = new MyType();
+    // CHECK: static auto const d_static = new MyType();
+
+    MyType * const d3 = new MyType();
+    // CHECK: auto const d3 = new MyType();
+
+    MyType * volatile d4 = new MyType();
+    // CHECK: auto volatile d4 = new MyType();
+  }
+
+  int (**func)(int, int) = new (int(*[5])(int,int));
+  // CHECK: int (**func)(int, int) = new (int(*[5])(int,int));
+
+  int *e = new int[5];
+  // CHECK: auto e = new int[5];
+
+  MyType *f(new MyType);
+  // CHECK: auto f(new MyType);
+
+  MyType *g{new MyType};
+  // CHECK: MyType *g{new MyType};
+}
Index: test/cpp11-migrate/UseAuto/new_cv_failing.cpp
===================================================================
--- /dev/null
+++ test/cpp11-migrate/UseAuto/new_cv_failing.cpp
@@ -0,0 +1,36 @@
+// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
+// RUN: cpp11-migrate -use-auto %t.cpp -- -std=c++11
+// RUN: FileCheck -input-file=%t.cpp %s
+// XFAIL: *
+
+// None of these tests can pass right now because TypeLoc information where CV
+// qualifiers are concerned is not reliable/available.
+
+class MyType {
+};
+
+int main (int argc, char **argv) {
+  const MyType *d = new MyType();
+  // CHECK: const auto *d = new MyType();
+
+  volatile MyType *d2 = new MyType();
+  // CHECK: volatile auto *d2 = new MyType();
+
+  const MyType * volatile e = new MyType();
+  // CHECK: const auto * volatile d = new MyType();
+
+  volatile MyType * const f = new MyType();
+  // CHECK: volatile auto * const d2 = new MyType();
+
+  const MyType *d5 = new const MyType();
+  // CHECK: auto d5 = new const MyType();
+
+  volatile MyType *d6 = new volatile MyType();
+  // CHECK: auto d6 = new volatile MyType();
+
+  const MyType * const d7 = new const MyType();
+  // CHECK: const auto d7 = new const MyType();
+
+  volatile MyType * volatile d8 = new volatile MyType();
+  // CHECK: volatile auto d8 = new volatile MyType();
+}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to