| //===-- ReplaceAutoPtrActions.cpp --- std::auto_ptr replacement -----------===// |
| // |
| // 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 "Core/Transform.h" |
| #include "ReplaceAutoPtrMatchers.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; |
| |
| Owner.addReplacementForCurrentTU( |
| 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; |
| |
| Owner.addReplacementForCurrentTU( |
| Replacement(SM, Range.getBegin(), 0, "std::move(")); |
| Owner.addReplacementForCurrentTU(Replacement(SM, Range.getEnd(), 0, ")")); |
| AcceptedChanges += 2; |
| } |