summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang-tools-extra/cpp11-migrate/UseAuto/UseAuto.cpp8
-rw-r--r--clang-tools-extra/cpp11-migrate/UseAuto/UseAutoActions.cpp52
-rw-r--r--clang-tools-extra/cpp11-migrate/UseAuto/UseAutoActions.h35
-rw-r--r--clang-tools-extra/cpp11-migrate/UseAuto/UseAutoMatchers.cpp35
-rw-r--r--clang-tools-extra/cpp11-migrate/UseAuto/UseAutoMatchers.h10
-rw-r--r--clang-tools-extra/test/cpp11-migrate/UseAuto/new.cpp52
-rw-r--r--clang-tools-extra/test/cpp11-migrate/UseAuto/new_cv_failing.cpp36
7 files changed, 211 insertions, 17 deletions
diff --git a/clang-tools-extra/cpp11-migrate/UseAuto/UseAuto.cpp b/clang-tools-extra/cpp11-migrate/UseAuto/UseAuto.cpp
index 31f867799b6..7a56e1c1250 100644
--- a/clang-tools-extra/cpp11-migrate/UseAuto/UseAuto.cpp
+++ b/clang-tools-extra/cpp11-migrate/UseAuto/UseAuto.cpp
@@ -35,9 +35,13 @@ int UseAutoTransform::apply(const FileContentsByPath &InputStates,
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";
diff --git a/clang-tools-extra/cpp11-migrate/UseAuto/UseAutoActions.cpp b/clang-tools-extra/cpp11-migrate/UseAuto/UseAutoActions.cpp
index 14986d8dca9..bd2599c4685 100644
--- a/clang-tools-extra/cpp11-migrate/UseAuto/UseAutoActions.cpp
+++ b/clang-tools-extra/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::ast_matchers;
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 @@ void UseAutoFixer::run(const MatchFinder::MatchResult &Result) {
++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.
+}
diff --git a/clang-tools-extra/cpp11-migrate/UseAuto/UseAutoActions.h b/clang-tools-extra/cpp11-migrate/UseAuto/UseAutoActions.h
index d6ea557b369..e28a45b10d1 100644
--- a/clang-tools-extra/cpp11-migrate/UseAuto/UseAutoActions.h
+++ b/clang-tools-extra/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;
diff --git a/clang-tools-extra/cpp11-migrate/UseAuto/UseAutoMatchers.cpp b/clang-tools-extra/cpp11-migrate/UseAuto/UseAutoMatchers.cpp
index b17708eabd4..08f9a7e52f6 100644
--- a/clang-tools-extra/cpp11-migrate/UseAuto/UseAutoMatchers.cpp
+++ b/clang-tools-extra/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 @@ TypeMatcher iteratorFromUsingDeclaration() {
}
} // namespace
-DeclarationMatcher makeIteratorMatcher() {
+DeclarationMatcher makeIteratorDeclMatcher() {
return varDecl(allOf(
hasWrittenNonListInitializer(),
unless(hasType(autoType())),
@@ -243,5 +245,32 @@ DeclarationMatcher makeIteratorMatcher() {
)
)
)
- )).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);
}
diff --git a/clang-tools-extra/cpp11-migrate/UseAuto/UseAutoMatchers.h b/clang-tools-extra/cpp11-migrate/UseAuto/UseAutoMatchers.h
index db160f8766e..1f09ad407cd 100644
--- a/clang-tools-extra/cpp11-migrate/UseAuto/UseAutoMatchers.h
+++ b/clang-tools-extra/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
diff --git a/clang-tools-extra/test/cpp11-migrate/UseAuto/new.cpp b/clang-tools-extra/test/cpp11-migrate/UseAuto/new.cpp
new file mode 100644
index 00000000000..911c0cd76bd
--- /dev/null
+++ b/clang-tools-extra/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};
+}
diff --git a/clang-tools-extra/test/cpp11-migrate/UseAuto/new_cv_failing.cpp b/clang-tools-extra/test/cpp11-migrate/UseAuto/new_cv_failing.cpp
new file mode 100644
index 00000000000..8e21018ef90
--- /dev/null
+++ b/clang-tools-extra/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();
+}
OpenPOWER on IntegriCloud