summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr
diff options
context:
space:
mode:
Diffstat (limited to 'clang-tools-extra/cpp11-migrate/ReplaceAutoPtr')
-rw-r--r--clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtr.cpp55
-rw-r--r--clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtr.h54
-rw-r--r--clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtrActions.cpp107
-rw-r--r--clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtrActions.h102
-rw-r--r--clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtrMatchers.cpp113
-rw-r--r--clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtrMatchers.h63
6 files changed, 494 insertions, 0 deletions
diff --git a/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtr.cpp b/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtr.cpp
new file mode 100644
index 00000000000..f3bc7a9f214
--- /dev/null
+++ b/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtr.cpp
@@ -0,0 +1,55 @@
+//===-- ReplaceAutoPtr.cpp ---------- std::auto_ptr replacement -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file provides the implementation of the ReplaceAutoPtrTransform
+/// class.
+///
+//===----------------------------------------------------------------------===//
+
+#include "ReplaceAutoPtr.h"
+#include "ReplaceAutoPtrActions.h"
+#include "ReplaceAutoPtrMatchers.h"
+
+#include "clang/Tooling/Refactoring.h"
+#include "clang/Tooling/Tooling.h"
+
+using namespace clang;
+using namespace clang::tooling;
+using namespace clang::ast_matchers;
+
+int
+ReplaceAutoPtrTransform::apply(FileOverrides &InputStates,
+ const CompilationDatabase &Database,
+ const std::vector<std::string> &SourcePaths) {
+ ClangTool Tool(Database, SourcePaths);
+
+ unsigned AcceptedChanges = 0;
+
+ MatchFinder Finder;
+ AutoPtrReplacer Replacer(getReplacements(), AcceptedChanges,
+ /*Owner=*/*this);
+ OwnershipTransferFixer Fixer(getReplacements(), AcceptedChanges,
+ /*Owner=*/*this);
+
+ Finder.addMatcher(makeAutoPtrTypeLocMatcher(), &Replacer);
+ Finder.addMatcher(makeAutoPtrUsingDeclMatcher(), &Replacer);
+ Finder.addMatcher(makeTransferOwnershipExprMatcher(), &Fixer);
+
+ setOverrides(InputStates);
+
+ if (Tool.run(createActionFactory(Finder))) {
+ llvm::errs() << "Error encountered during translation.\n";
+ return 1;
+ }
+
+ setAcceptedChanges(AcceptedChanges);
+
+ return 0;
+}
diff --git a/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtr.h b/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtr.h
new file mode 100644
index 00000000000..f4e8f6fcc2c
--- /dev/null
+++ b/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtr.h
@@ -0,0 +1,54 @@
+//===-- ReplaceAutoPtr.h ------------ std::auto_ptr replacement -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file provides the declaration of the ReplaceAutoPtrTransform
+/// class.
+///
+//===----------------------------------------------------------------------===//
+#ifndef CPP11_MIGRATE_REPLACE_AUTO_PTR_H
+#define CPP11_MIGRATE_REPLACE_AUTO_PTR_H
+
+#include "Core/Transform.h"
+#include "llvm/Support/Compiler.h"
+
+/// \brief Subclass of Transform that transforms the deprecated \c std::auto_ptr
+/// into the C++11 \c std::unique_ptr.
+///
+/// Note that both the \c std::auto_ptr type and the transfer of ownership are
+/// transformed. \c std::auto_ptr provides two ways to transfer the ownership,
+/// the copy-constructor and the assignment operator. Unlike most classes theses
+/// operations do not 'copy' the resource but they 'steal' it.
+/// \c std::unique_ptr uses move semantics instead, which makes the intent of
+/// transferring the resource explicit. This difference between the two smart
+/// pointers requires to wrap the copy-ctor and assign-operator with
+/// \c std::move().
+///
+/// For example, given:
+/// \code
+/// std::auto_ptr<int> i, j;
+/// i = j;
+/// \endcode
+/// the code is transformed to:
+/// \code
+/// std::unique_ptr<int> i, j;
+/// i = std::move(j);
+/// \endcode
+class ReplaceAutoPtrTransform : public Transform {
+public:
+ ReplaceAutoPtrTransform(const TransformOptions &Options)
+ : Transform("ReplaceAutoPtr", Options) {}
+
+ /// \see Transform::run().
+ virtual int apply(FileOverrides &InputStates,
+ const clang::tooling::CompilationDatabase &Database,
+ const std::vector<std::string> &SourcePaths) LLVM_OVERRIDE;
+};
+
+#endif // CPP11_MIGRATE_REPLACE_AUTO_PTR_H
diff --git a/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtrActions.cpp b/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtrActions.cpp
new file mode 100644
index 00000000000..d80c0795ce2
--- /dev/null
+++ b/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtrActions.cpp
@@ -0,0 +1,107 @@
+//===-- ReplaceAutoPtrActions.cpp --- std::auto_ptr replacement -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file contains the definition of the ASTMatcher callback
+/// for the ReplaceAutoPtr transform.
+///
+//===----------------------------------------------------------------------===//
+
+#include "ReplaceAutoPtrActions.h"
+#include "ReplaceAutoPtrMatchers.h"
+#include "Core/Transform.h"
+
+#include "clang/AST/ASTContext.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang;
+using namespace clang::tooling;
+using namespace clang::ast_matchers;
+
+namespace {
+
+/// \brief Verifies that the token at \p BeginningOfToken is 'auto_ptr'.
+bool checkTokenIsAutoPtr(clang::SourceLocation BeginningOfToken,
+ const clang::SourceManager &SM,
+ const clang::LangOptions &LangOptions) {
+ llvm::SmallVector<char, 8> Buffer;
+ bool Invalid = false;
+ llvm::StringRef Res =
+ Lexer::getSpelling(BeginningOfToken, Buffer, SM, LangOptions, &Invalid);
+
+ if (Invalid)
+ return false;
+
+ return Res == "auto_ptr";
+}
+
+} // end anonymous namespace
+
+void AutoPtrReplacer::run(const MatchFinder::MatchResult &Result) {
+ SourceManager &SM = *Result.SourceManager;
+ SourceLocation IdentifierLoc;
+
+ if (const TypeLoc *TL = Result.Nodes.getNodeAs<TypeLoc>(AutoPtrTokenId)) {
+ IdentifierLoc = locateFromTypeLoc(*TL, SM);
+ } else {
+ const UsingDecl *D = Result.Nodes.getNodeAs<UsingDecl>(AutoPtrTokenId);
+ assert(D && "Bad Callback. No node provided.");
+ IdentifierLoc = locateFromUsingDecl(D, SM);
+ }
+
+ if (IdentifierLoc.isMacroID())
+ IdentifierLoc = SM.getSpellingLoc(IdentifierLoc);
+
+ if (!Owner.isFileModifiable(SM, IdentifierLoc))
+ return;
+
+ // make sure that only the 'auto_ptr' token is replaced and not the template
+ // aliases [temp.alias]
+ if (!checkTokenIsAutoPtr(IdentifierLoc, SM, LangOptions()))
+ return;
+
+ Replace.insert(
+ Replacement(SM, IdentifierLoc, strlen("auto_ptr"), "unique_ptr"));
+ ++AcceptedChanges;
+}
+
+SourceLocation AutoPtrReplacer::locateFromTypeLoc(TypeLoc AutoPtrTypeLoc,
+ const SourceManager &SM) {
+ TemplateSpecializationTypeLoc TL =
+ AutoPtrTypeLoc.getAs<TemplateSpecializationTypeLoc>();
+ if (TL.isNull())
+ return SourceLocation();
+
+ return TL.getTemplateNameLoc();
+}
+
+SourceLocation
+AutoPtrReplacer::locateFromUsingDecl(const UsingDecl *UsingAutoPtrDecl,
+ const SourceManager &SM) {
+ return UsingAutoPtrDecl->getNameInfo().getBeginLoc();
+}
+
+void OwnershipTransferFixer::run(const MatchFinder::MatchResult &Result) {
+ SourceManager &SM = *Result.SourceManager;
+ const Expr *E = Result.Nodes.getNodeAs<Expr>(AutoPtrOwnershipTransferId);
+ assert(E && "Bad Callback. No node provided.");
+
+ CharSourceRange Range = Lexer::makeFileCharRange(
+ CharSourceRange::getTokenRange(E->getSourceRange()), SM, LangOptions());
+
+ if (Range.isInvalid())
+ return;
+
+ if (!Owner.isFileModifiable(SM, Range.getBegin()))
+ return;
+
+ Replace.insert(Replacement(SM, Range.getBegin(), 0, "std::move("));
+ Replace.insert(Replacement(SM, Range.getEnd(), 0, ")"));
+ AcceptedChanges += 2;
+}
diff --git a/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtrActions.h b/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtrActions.h
new file mode 100644
index 00000000000..7369e9e5c46
--- /dev/null
+++ b/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtrActions.h
@@ -0,0 +1,102 @@
+//===-- ReplaceAutoPtrActions.h ----- std::auto_ptr replacement -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file contains the declaration of the ASTMatcher callback
+/// for the ReplaceAutoPtr transform.
+///
+//===----------------------------------------------------------------------===//
+#ifndef CPP11_MIGRATE_REPLACE_AUTO_PTR_ACTIONS_H
+#define CPP11_MIGRATE_REPLACE_AUTO_PTR_ACTIONS_H
+
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Tooling/Refactoring.h"
+
+class Transform;
+
+/// \brief The callback to be used when replacing the \c std::auto_ptr types and
+/// using declarations.
+class AutoPtrReplacer : public clang::ast_matchers::MatchFinder::MatchCallback {
+public:
+ AutoPtrReplacer(clang::tooling::Replacements &Replace,
+ unsigned &AcceptedChanges, const Transform &Owner)
+ : Replace(Replace), AcceptedChanges(AcceptedChanges), Owner(Owner) {}
+
+ /// \brief Entry point to the callback called when matches are made.
+ virtual void run(const clang::ast_matchers::MatchFinder::MatchResult &Result)
+ LLVM_OVERRIDE;
+
+private:
+ /// \brief Locates the \c auto_ptr token when it is referred by a \c TypeLoc.
+ ///
+ /// \code
+ /// std::auto_ptr<int> i;
+ /// ^~~~~~~~~~~~~
+ /// \endcode
+ /// The caret represents the location returned and the tildes cover the
+ /// parameter \p AutoPtrTypeLoc.
+ ///
+ /// \return An invalid \c SourceLocation if not found, otherwise the location
+ /// of the beginning of the \c auto_ptr token.
+ clang::SourceLocation locateFromTypeLoc(clang::TypeLoc AutoPtrTypeLoc,
+ const clang::SourceManager &SM);
+
+ /// \brief Locates the \c auto_ptr token in using declarations.
+ ///
+ /// \code
+ /// using std::auto_ptr;
+ /// ^
+ /// \endcode
+ /// The caret represents the location returned.
+ ///
+ /// \return An invalid \c SourceLocation if not found, otherwise the
+ /// location of the beginning of the \c auto_ptr token.
+ clang::SourceLocation
+ locateFromUsingDecl(const clang::UsingDecl *UsingAutoPtrDecl,
+ const clang::SourceManager &SM);
+
+private:
+ clang::tooling::Replacements &Replace;
+ unsigned &AcceptedChanges;
+ const Transform &Owner;
+};
+
+/// \brief The callback to be used to fix the ownership transfers of
+/// \c auto_ptr,
+///
+/// \c unique_ptr requires to use \c std::move() explicitly in order to transfer
+/// the ownership.
+///
+/// Given:
+/// \code
+/// std::auto_ptr<int> a, b;
+/// a = b;
+/// \endcode
+/// The last statement is transformed to:
+/// \code
+/// a = std::move(b);
+/// \endcode
+class OwnershipTransferFixer
+ : public clang::ast_matchers::MatchFinder::MatchCallback {
+public:
+ OwnershipTransferFixer(clang::tooling::Replacements &Replace,
+ unsigned &AcceptedChanges, const Transform &Owner)
+ : Replace(Replace), AcceptedChanges(AcceptedChanges), Owner(Owner) {}
+
+ /// \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;
+ unsigned &AcceptedChanges;
+ const Transform &Owner;
+};
+
+#endif // CPP11_MIGRATE_REPLACE_AUTO_PTR_ACTIONS_H
diff --git a/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtrMatchers.cpp b/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtrMatchers.cpp
new file mode 100644
index 00000000000..64bff2c2211
--- /dev/null
+++ b/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtrMatchers.cpp
@@ -0,0 +1,113 @@
+//===-- ReplaceAutoPtrMatchers.cpp - std::auto_ptr replacement -*- C++ -*--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file contains the definitions for matcher-generating functions
+/// and names for bound nodes found by AST matchers.
+///
+//===----------------------------------------------------------------------===//
+
+#include "ReplaceAutoPtrMatchers.h"
+
+const char *AutoPtrTokenId = "AutoPtrTokenId";
+const char *AutoPtrOwnershipTransferId = "AutoPtrOwnershipTransferId";
+
+namespace clang {
+namespace ast_matchers {
+
+/// \brief Matches expressions that are lvalues.
+///
+/// In the following example, a[0] matches expr(isLValue()):
+/// \code
+/// std::string a[2];
+/// std::string b;
+/// b = a[0];
+/// b = "this string won't match";
+/// \endcode
+AST_MATCHER(Expr, isLValue) {
+ return Node.getValueKind() == VK_LValue;
+}
+
+/// \brief Matches declarations whose declaration context is the C++ standard
+/// library namespace \c std.
+///
+/// Note that inline namespaces are silently ignored during the lookup since
+/// both libstdc++ and libc++ are known to use them for versioning purposes.
+///
+/// Given
+/// \code
+/// namespace ns {
+/// struct my_type {};
+/// using namespace std;
+/// }
+///
+/// using std::vector;
+/// using ns::my_type;
+/// using ns::list;
+/// \endcode
+/// usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(isFromStdNamespace())))
+/// matches "using std::vector" and "using ns::list".
+AST_MATCHER(Decl, isFromStdNamespace) {
+ const DeclContext *D = Node.getDeclContext();
+
+ while (D->isInlineNamespace())
+ D = D->getParent();
+
+ if (!D->isNamespace() || !D->getParent()->isTranslationUnit())
+ return false;
+
+ const IdentifierInfo *Info = cast<NamespaceDecl>(D)->getIdentifier();
+
+ return Info && Info->isStr("std");
+}
+
+} // end namespace ast_matchers
+} // end namespace clang
+
+using namespace clang;
+using namespace clang::ast_matchers;
+
+// shared matchers
+static DeclarationMatcher AutoPtrDecl =
+ recordDecl(hasName("auto_ptr"), isFromStdNamespace());
+
+static TypeMatcher AutoPtrType = qualType(hasDeclaration(AutoPtrDecl));
+
+// Matcher that finds expressions that are candidates to be wrapped with
+// 'std::move()'.
+//
+// Binds the id \c AutoPtrOwnershipTransferId to the expression.
+static StatementMatcher MovableArgumentMatcher = expr(
+ allOf(isLValue(), hasType(AutoPtrType))).bind(AutoPtrOwnershipTransferId);
+
+TypeLocMatcher makeAutoPtrTypeLocMatcher() {
+ // skip elaboratedType() as the named type will match soon thereafter.
+ return typeLoc(loc(qualType(AutoPtrType, unless(elaboratedType()))))
+ .bind(AutoPtrTokenId);
+}
+
+DeclarationMatcher makeAutoPtrUsingDeclMatcher() {
+ return usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(
+ allOf(hasName("auto_ptr"), isFromStdNamespace())))).bind(AutoPtrTokenId);
+}
+
+StatementMatcher makeTransferOwnershipExprMatcher() {
+ StatementMatcher assignOperator =
+ operatorCallExpr(allOf(
+ hasOverloadedOperatorName("="),
+ callee(methodDecl(ofClass(AutoPtrDecl))),
+ hasArgument(1, MovableArgumentMatcher)));
+
+ StatementMatcher copyCtor =
+ constructExpr(allOf(hasType(AutoPtrType),
+ argumentCountIs(1),
+ hasArgument(0, MovableArgumentMatcher)));
+
+ return anyOf(assignOperator, copyCtor);
+}
diff --git a/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtrMatchers.h b/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtrMatchers.h
new file mode 100644
index 00000000000..5d1e7bcec6e
--- /dev/null
+++ b/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtrMatchers.h
@@ -0,0 +1,63 @@
+//===-- ReplaceAutoPtrMatchers.h --- std::auto_ptr replacement -*- C++ -*--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file contains the declarations for matcher-generating functions
+/// and names for bound nodes found by AST matchers.
+///
+//===----------------------------------------------------------------------===//
+#ifndef CPP11_MIGRATE_REPLACE_AUTO_PTR_MATCHERS_H
+#define CPP11_MIGRATE_REPLACE_AUTO_PTR_MATCHERS_H
+
+#include "clang/ASTMatchers/ASTMatchers.h"
+
+/// Names to bind with matched expressions.
+extern const char *AutoPtrTokenId;
+extern const char *AutoPtrOwnershipTransferId;
+
+/// \brief Creates a matcher that finds the locations of types referring to the
+/// \c std::auto_ptr() type.
+///
+/// \code
+/// std::auto_ptr<int> a;
+/// ^~~~~~~~~~~~~
+///
+/// typedef std::auto_ptr<int> int_ptr_t;
+/// ^~~~~~~~~~~~~
+///
+/// std::auto_ptr<int> fn(std::auto_ptr<int>);
+/// ^~~~~~~~~~~~~ ^~~~~~~~~~~~~
+///
+/// <etc...>
+/// \endcode
+clang::ast_matchers::TypeLocMatcher makeAutoPtrTypeLocMatcher();
+
+/// \brief Creates a matcher that finds the using declarations referring to
+/// \c std::auto_ptr.
+///
+/// \code
+/// using std::auto_ptr;
+/// ^~~~~~~~~~~~~~~~~~~
+/// \endcode
+clang::ast_matchers::DeclarationMatcher makeAutoPtrUsingDeclMatcher();
+
+/// \brief Creates a matcher that finds the \c std::auto_ptr copy-ctor and
+/// assign-operator expressions.
+///
+/// \c AutoPtrOwnershipTransferId is assigned to the argument of the expression,
+/// this is the part that has to be wrapped by \c std::move().
+///
+/// \code
+/// std::auto_ptr<int> i, j;
+/// i = j;
+/// ~~~~^
+/// \endcode
+clang::ast_matchers::StatementMatcher makeTransferOwnershipExprMatcher();
+
+#endif // CPP11_MIGRATE_REPLACE_AUTO_PTR_MATCHERS_H
OpenPOWER on IntegriCloud