summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/cpp11-migrate/AddOverride/AddOverrideActions.cpp
blob: 197befa4f4fa009485f977334994d2d96459b007 (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
//===-- AddOverride/AddOverrideActions.cpp - add C++11 override-*- 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 AddOverrideFixer class
///  which is used as an ASTMatcher callback.
///
//===----------------------------------------------------------------------===//

#include "AddOverrideActions.h"
#include "AddOverrideMatchers.h"

#include "clang/Basic/CharInfo.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Lex/Lexer.h"

using namespace clang::ast_matchers;
using namespace clang::tooling;
using namespace clang;

void AddOverrideFixer::run(const MatchFinder::MatchResult &Result) {
  SourceManager &SM = *Result.SourceManager;

  const CXXMethodDecl *M = Result.Nodes.getDeclAs<CXXMethodDecl>(MethodId);
  assert(M && "Bad Callback. No node provided");

  // Check that the method declaration in the main file
  if (!SM.isFromMainFile(M->getLocStart()))
    return;

  if (!SM.isFromMainFile(M->getLocStart()))
    return;

  // First check that there isn't already an override attribute.
  if (M->hasAttr<OverrideAttr>())
    return;

  // FIXME: Pure methods are not supported yet as it is difficult to track down
  // the location of '= 0'.
  if (M->isPure())
    return;

  if (const FunctionDecl *TemplateMethod = M->getTemplateInstantiationPattern())
    M = cast<CXXMethodDecl>(TemplateMethod);

  if (M->getParent()->hasAnyDependentBases())
    return;

  SourceLocation StartLoc;
  if (M->hasInlineBody()) {
    // Start at the beginning of the body and rewind back to the last
    // non-whitespace character. We will insert the override keyword
    // after that character.
    // FIXME: This transform won't work if there is a comment between
    // the end of the function prototype and the start of the body.
    StartLoc = M->getBody()->getLocStart();
    do {
      StartLoc = StartLoc.getLocWithOffset(-1);
    } while (isWhitespace(*FullSourceLoc(StartLoc, SM).getCharacterData()));
    StartLoc = StartLoc.getLocWithOffset(1);
  } else {
    StartLoc = SM.getSpellingLoc(M->getLocEnd());
    StartLoc = Lexer::getLocForEndOfToken(StartLoc, 0, SM, LangOptions());
  }
  Replace.insert(tooling::Replacement(SM, StartLoc, 0, " override"));
  ++AcceptedChanges;
}
OpenPOWER on IntegriCloud