summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtrActions.cpp
blob: f538d94d53a95d44e46ffb9da5f1d0f7b1d1dc39 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
//===-- 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 "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;
}
OpenPOWER on IntegriCloud