mirror of
https://github.com/intel/llvm.git
synced 2026-01-19 09:31:59 +08:00
cpp11-migrate: Add option to detect and use macros that expand to 'override'
Added a new option -override-macros which causes the, the add-override transform to detect macros that expand to 'override' (like LLVM_OVERRIDE) and use these macros instead of the override keyword directly. llvm-svn: 183001
This commit is contained in:
@@ -16,15 +16,21 @@
|
||||
#include "AddOverride.h"
|
||||
#include "AddOverrideActions.h"
|
||||
#include "AddOverrideMatchers.h"
|
||||
#include "clang/Frontend/CompilerInstance.h"
|
||||
#include "clang/Frontend/FrontendActions.h"
|
||||
#include "clang/Rewrite/Core/Rewriter.h"
|
||||
#include "clang/Tooling/Refactoring.h"
|
||||
#include "clang/Tooling/Tooling.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
|
||||
using clang::ast_matchers::MatchFinder;
|
||||
using namespace clang::tooling;
|
||||
using namespace clang;
|
||||
|
||||
static llvm::cl::opt<bool> DetectMacros(
|
||||
"override-macros",
|
||||
llvm::cl::desc("Detect and use macros that expand to the 'override' keyword."));
|
||||
|
||||
int AddOverrideTransform::apply(const FileContentsByPath &InputStates,
|
||||
RiskLevel MaxRisk,
|
||||
const CompilationDatabase &Database,
|
||||
@@ -41,7 +47,10 @@ int AddOverrideTransform::apply(const FileContentsByPath &InputStates,
|
||||
unsigned AcceptedChanges = 0;
|
||||
|
||||
MatchFinder Finder;
|
||||
AddOverrideFixer Fixer(AddOverrideTool.getReplacements(), AcceptedChanges);
|
||||
AddOverrideFixer Fixer(AddOverrideTool.getReplacements(), AcceptedChanges,
|
||||
DetectMacros);
|
||||
// Make Fixer available to handleBeginSource().
|
||||
this->Fixer = &Fixer;
|
||||
|
||||
Finder.addMatcher(makeCandidateForOverrideAttrMatcher(), &Fixer);
|
||||
|
||||
@@ -62,3 +71,10 @@ int AddOverrideTransform::apply(const FileContentsByPath &InputStates,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool AddOverrideTransform::handleBeginSource(clang::CompilerInstance &CI,
|
||||
llvm::StringRef Filename) {
|
||||
assert(Fixer != NULL && "Fixer must be set");
|
||||
Fixer->setPreprocessor(CI.getPreprocessor());
|
||||
return Transform::handleBeginSource(CI, Filename);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#include "Core/Transform.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
|
||||
class AddOverrideFixer;
|
||||
|
||||
/// \brief Subclass of Transform that adds the C++11 override keyword to
|
||||
/// member functions overriding base class virtual functions.
|
||||
class AddOverrideTransform : public Transform {
|
||||
@@ -33,6 +35,12 @@ public:
|
||||
const clang::tooling::CompilationDatabase &Database,
|
||||
const std::vector<std::string> &SourcePaths,
|
||||
FileContentsByPath &ResultStates) LLVM_OVERRIDE;
|
||||
|
||||
virtual bool handleBeginSource(clang::CompilerInstance &CI,
|
||||
llvm::StringRef Filename) LLVM_OVERRIDE;
|
||||
|
||||
private:
|
||||
AddOverrideFixer *Fixer;
|
||||
};
|
||||
|
||||
#endif // LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_ADD_OVERRIDE_H
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "clang/AST/Attr.h"
|
||||
#include "clang/AST/RecursiveASTVisitor.h"
|
||||
#include "clang/Lex/Lexer.h"
|
||||
#include "clang/Lex/Preprocessor.h"
|
||||
|
||||
using namespace clang::ast_matchers;
|
||||
using namespace clang::tooling;
|
||||
@@ -85,6 +86,15 @@ void AddOverrideFixer::run(const MatchFinder::MatchResult &Result) {
|
||||
StartLoc = SM.getSpellingLoc(M->getLocEnd());
|
||||
StartLoc = Lexer::getLocForEndOfToken(StartLoc, 0, SM, LangOptions());
|
||||
}
|
||||
Replace.insert(tooling::Replacement(SM, StartLoc, 0, " override"));
|
||||
|
||||
std::string ReplacementText = " override";
|
||||
if (DetectMacros) {
|
||||
assert(PP != 0 && "No access to Preprocessor object for macro detection");
|
||||
clang::TokenValue Tokens[] = { PP->getIdentifierInfo("override") };
|
||||
llvm::StringRef MacroName = PP->getLastMacroWithSpelling(StartLoc, Tokens);
|
||||
if (!MacroName.empty())
|
||||
ReplacementText = (" " + MacroName).str();
|
||||
}
|
||||
Replace.insert(tooling::Replacement(SM, StartLoc, 0, ReplacementText));
|
||||
++AcceptedChanges;
|
||||
}
|
||||
|
||||
@@ -24,15 +24,20 @@
|
||||
class AddOverrideFixer : public clang::ast_matchers::MatchFinder::MatchCallback {
|
||||
public:
|
||||
AddOverrideFixer(clang::tooling::Replacements &Replace,
|
||||
unsigned &AcceptedChanges) :
|
||||
Replace(Replace), AcceptedChanges(AcceptedChanges) {}
|
||||
unsigned &AcceptedChanges, bool DetectMacros)
|
||||
: Replace(Replace), AcceptedChanges(AcceptedChanges),
|
||||
DetectMacros(DetectMacros) {}
|
||||
|
||||
/// \brief Entry point to the callback called when matches are made.
|
||||
virtual void run(const clang::ast_matchers::MatchFinder::MatchResult &Result);
|
||||
|
||||
void setPreprocessor(clang::Preprocessor &PP) { this->PP = &PP; }
|
||||
|
||||
private:
|
||||
clang::Preprocessor *PP;
|
||||
clang::tooling::Replacements &Replace;
|
||||
unsigned &AcceptedChanges;
|
||||
bool DetectMacros;
|
||||
};
|
||||
|
||||
#endif // LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_ADD_OVERRIDE_ACTIONS_H
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
|
||||
// RUN: cpp11-migrate -add-override %t.cpp -- -I %S -std=c++11
|
||||
// RUN: FileCheck -input-file=%t.cpp %s
|
||||
// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
|
||||
// RUN: cpp11-migrate -add-override -override-macros %t.cpp -- -I %S -std=c++11
|
||||
// RUN: FileCheck --check-prefix=MACRO --input-file=%t.cpp %s
|
||||
|
||||
class A {
|
||||
public:
|
||||
struct A {
|
||||
virtual ~A();
|
||||
// CHECK: virtual ~A();
|
||||
void f();
|
||||
@@ -14,81 +16,76 @@ public:
|
||||
};
|
||||
|
||||
// Test that override isn't added to non-virtual functions.
|
||||
class B : public A {
|
||||
public:
|
||||
struct B : public A {
|
||||
void f();
|
||||
// CHECK: class B
|
||||
// CHECK: void f();
|
||||
// CHECK: struct B
|
||||
// CHECK-NEXT: void f();
|
||||
};
|
||||
|
||||
// Test that override is added to functions that override virtual functions.
|
||||
class C : public A {
|
||||
public:
|
||||
struct C : public A {
|
||||
void h() const;
|
||||
// CHECK: class C
|
||||
// CHECK: void h() const override;
|
||||
// CHECK: struct C
|
||||
// CHECK-NEXT: void h() const override;
|
||||
// MACRO: struct C
|
||||
// MACRO-NEXT: void h() const override;
|
||||
};
|
||||
|
||||
// Test that override isn't add to functions that overload but not override.
|
||||
class D : public A {
|
||||
public:
|
||||
struct D : public A {
|
||||
void h();
|
||||
// CHECK: class D
|
||||
// CHECK: void h();
|
||||
// CHECK: struct D
|
||||
// CHECK-NEXT: void h();
|
||||
};
|
||||
|
||||
// Test that override isn't added again to functions that already have it.
|
||||
class E : public A {
|
||||
public:
|
||||
struct E : public A {
|
||||
void h() const override;
|
||||
// CHECK: class E
|
||||
// CHECK: void h() const override;
|
||||
// CHECK: struct E
|
||||
// CHECK-NEXT: void h() const override;
|
||||
// MACRO: struct E
|
||||
// MACRO-NEXT: void h() const override;
|
||||
};
|
||||
|
||||
// Test that override isn't added to the destructor.
|
||||
class F : public A {
|
||||
public:
|
||||
struct F : public A {
|
||||
virtual ~F();
|
||||
// CHECK: class F
|
||||
// CHECK: virtual ~F();
|
||||
// CHECK: struct F
|
||||
// CHECK-NEXT: virtual ~F();
|
||||
};
|
||||
|
||||
// Test that override is placed before any end of line comments.
|
||||
class G : public A {
|
||||
public:
|
||||
struct G : public A {
|
||||
void h() const; // comment
|
||||
void i() // comment
|
||||
{}
|
||||
// CHECK: class G
|
||||
// CHECK: void h() const override; // comment
|
||||
// CHECK: void i() override // comment
|
||||
// CHECK: struct G
|
||||
// CHECK-NEXT: void h() const override; // comment
|
||||
// CHECK-NEXT: void i() override // comment
|
||||
// CHECK-NEXT: {}
|
||||
};
|
||||
|
||||
// Test that override is placed correctly if there is an inline body.
|
||||
class H : public A {
|
||||
public:
|
||||
struct H : public A {
|
||||
void h() const { }
|
||||
// CHECK: class H
|
||||
// CHECK: void h() const override { }
|
||||
// CHECK: struct H
|
||||
// CHECK-NEXT: void h() const override { }
|
||||
};
|
||||
|
||||
// Test that override is placed correctly if there is a body on the next line.
|
||||
class I : public A {
|
||||
public:
|
||||
struct I : public A {
|
||||
void h() const
|
||||
{ }
|
||||
// CHECK: class I
|
||||
// CHECK: void h() const override
|
||||
// CHECK: { }
|
||||
// CHECK: struct I
|
||||
// CHECK-NEXT: void h() const override
|
||||
// CHECK-NEXT: { }
|
||||
};
|
||||
|
||||
// Test that override is placed correctly if there is a body outside the class.
|
||||
class J : public A {
|
||||
public:
|
||||
struct J : public A {
|
||||
void h() const;
|
||||
// CHECK: class J
|
||||
// CHECK: void h() const override;
|
||||
// CHECK: struct J
|
||||
// CHECK-NEXT: void h() const override;
|
||||
};
|
||||
|
||||
void J::h() const {
|
||||
@@ -96,22 +93,33 @@ void J::h() const {
|
||||
}
|
||||
|
||||
// Test that override is placed correctly if there is a trailing return type.
|
||||
class K : public A {
|
||||
public:
|
||||
struct K : public A {
|
||||
auto h() const -> void;
|
||||
// CHECK: class K
|
||||
// CHECK: auto h() const -> void override;
|
||||
// CHECK: struct K
|
||||
// CHECK-NEXT: auto h() const -> void override;
|
||||
};
|
||||
|
||||
// Test that override isn't added if it is already specified via a macro.
|
||||
class L : public A {
|
||||
public:
|
||||
#define LLVM_OVERRIDE override
|
||||
|
||||
// Test that override isn't added if it is already specified via a macro.
|
||||
struct L : public A {
|
||||
void h() const LLVM_OVERRIDE;
|
||||
// CHECK: class L
|
||||
// CHECK: void h() const LLVM_OVERRIDE;
|
||||
// CHECK: struct L
|
||||
// CHECK-NEXT: void h() const LLVM_OVERRIDE;
|
||||
// MACRO: struct L
|
||||
// MACRO-NEXT: void h() const LLVM_OVERRIDE;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct M : public A {
|
||||
virtual void i();
|
||||
// CHECK: struct M
|
||||
// CHECK-NEXT: virtual void i() override;
|
||||
// MACRO: struct M
|
||||
// MACRO-NEXT: virtual void i() LLVM_OVERRIDE;
|
||||
};
|
||||
M<int> b;
|
||||
|
||||
// Test that override isn't added at the wrong place for "pure overrides"
|
||||
struct APure {
|
||||
virtual APure *clone() = 0;
|
||||
@@ -137,16 +145,17 @@ struct Base2 {};
|
||||
template<typename T> struct Derived : T {
|
||||
void f(); // adding 'override' here will break instantiation of Derived<Base2>
|
||||
// CHECK: struct Derived
|
||||
// CHECK: void f();
|
||||
// CHECK-NEXT: void f();
|
||||
};
|
||||
Derived<Base1> d1;
|
||||
Derived<Base2> d2;
|
||||
|
||||
template <typename T>
|
||||
class M : public A {
|
||||
public:
|
||||
virtual void i();
|
||||
// CHECK: class M : public A {
|
||||
// CHECK: virtual void i() override;
|
||||
#undef LLVM_OVERRIDE
|
||||
|
||||
struct N : public A {
|
||||
void h() const;
|
||||
// CHECK: struct N
|
||||
// CHECK-NEXT: void h() const override;
|
||||
// MACRO: struct N
|
||||
// MACRO-NEXT: void h() const override;
|
||||
};
|
||||
M<int> b;
|
||||
|
||||
Reference in New Issue
Block a user