summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clang-tidy/misc
diff options
context:
space:
mode:
Diffstat (limited to 'clang-tools-extra/clang-tidy/misc')
-rw-r--r--clang-tools-extra/clang-tidy/misc/CMakeLists.txt1
-rw-r--r--clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp4
-rw-r--r--clang-tools-extra/clang-tidy/misc/UseOverride.cpp131
-rw-r--r--clang-tools-extra/clang-tidy/misc/UseOverride.h29
4 files changed, 165 insertions, 0 deletions
diff --git a/clang-tools-extra/clang-tidy/misc/CMakeLists.txt b/clang-tools-extra/clang-tidy/misc/CMakeLists.txt
index 3dd97bf0b4f..796dc15062d 100644
--- a/clang-tools-extra/clang-tidy/misc/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/misc/CMakeLists.txt
@@ -4,6 +4,7 @@ add_clang_library(clangTidyMiscModule
ArgumentCommentCheck.cpp
MiscTidyModule.cpp
RedundantSmartptrGet.cpp
+ UseOverride.cpp
LINK_LIBS
clangAST
diff --git a/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp b/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
index b89e2dcad48..28a2f0be788 100644
--- a/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
@@ -12,6 +12,7 @@
#include "../ClangTidyModuleRegistry.h"
#include "ArgumentCommentCheck.h"
#include "RedundantSmartptrGet.h"
+#include "UseOverride.h"
namespace clang {
namespace tidy {
@@ -25,6 +26,9 @@ public:
CheckFactories.addCheckFactory(
"misc-redundant-smartptr-get",
new ClangTidyCheckFactory<RedundantSmartptrGet>());
+ CheckFactories.addCheckFactory(
+ "misc-use-override",
+ new ClangTidyCheckFactory<UseOverride>());
}
};
diff --git a/clang-tools-extra/clang-tidy/misc/UseOverride.cpp b/clang-tools-extra/clang-tidy/misc/UseOverride.cpp
new file mode 100644
index 00000000000..3d2411ec56a
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/misc/UseOverride.cpp
@@ -0,0 +1,131 @@
+//===--- UseOverride.cpp - clang-tidy -------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "UseOverride.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+
+void UseOverride::registerMatchers(MatchFinder *Finder) {
+ Finder->addMatcher(methodDecl(isOverride()).bind("method"), this);
+}
+
+// Re-lex the tokens to get precise locations to insert 'override' and remove
+// 'virtual'.
+static SmallVector<Token, 16> ParseTokens(CharSourceRange Range,
+ const SourceManager &Sources,
+ LangOptions LangOpts) {
+ std::pair<FileID, unsigned> LocInfo =
+ Sources.getDecomposedLoc(Range.getBegin());
+ StringRef File = Sources.getBufferData(LocInfo.first);
+ const char *TokenBegin = File.data() + LocInfo.second;
+ Lexer RawLexer(Sources.getLocForStartOfFile(LocInfo.first), LangOpts,
+ File.begin(), TokenBegin, File.end());
+ SmallVector<Token, 16> Tokens;
+ Token Tok;
+ while (!RawLexer.LexFromRawLexer(Tok)) {
+ if (Tok.is(tok::semi) || Tok.is(tok::l_brace))
+ break;
+ if (Sources.isBeforeInTranslationUnit(Range.getEnd(), Tok.getLocation()))
+ break;
+ Tokens.push_back(Tok);
+ }
+ return Tokens;
+}
+
+static StringRef GetText(const Token& Tok, const SourceManager &Sources) {
+ return {Sources.getCharacterData(Tok.getLocation()), Tok.getLength()};
+}
+
+void UseOverride::check(const MatchFinder::MatchResult &Result) {
+ const FunctionDecl *Method = Result.Nodes.getStmtAs<FunctionDecl>("method");
+ const SourceManager &Sources = *Result.SourceManager;
+
+ assert(Method != nullptr);
+ if (Method->getInstantiatedFromMemberFunction() != nullptr)
+ Method = Method->getInstantiatedFromMemberFunction();
+
+ if (Method->isImplicit() || Method->getLocation().isMacroID() ||
+ Method->isOutOfLine())
+ return;
+
+ if (Method->getAttr<clang::OverrideAttr>() != nullptr &&
+ !Method->isVirtualAsWritten())
+ return; // Nothing to do.
+
+ DiagnosticBuilder Diag = diag(Method->getLocation(),
+ "Prefer using 'override' instead of 'virtual'");
+
+ CharSourceRange FileRange =
+ Lexer::makeFileCharRange(CharSourceRange::getTokenRange(
+ Method->getLocStart(), Method->getLocEnd()),
+ Sources, Result.Context->getLangOpts());
+
+ if (!FileRange.isValid())
+ return;
+
+ // FIXME: Instead of re-lexing and looking for specific macros such as
+ // 'ABSTRACT', properly store the location of 'virtual' and '= 0' in each
+ // FunctionDecl.
+ SmallVector<Token, 16> Tokens = ParseTokens(FileRange, Sources,
+ Result.Context->getLangOpts());
+
+ // Add 'override' on inline declarations that don't already have it.
+ if (Method->getAttr<clang::OverrideAttr>() == nullptr) {
+ SourceLocation InsertLoc;
+ StringRef ReplacementText = "override ";
+
+ if (Method->hasAttrs()) {
+ for (const clang::Attr *attr : Method->getAttrs()) {
+ if (!attr->isImplicit()) {
+ InsertLoc = Sources.getExpansionLoc(attr->getLocation());
+ break;
+ }
+ }
+ }
+
+ if (InsertLoc.isInvalid() && Method->doesThisDeclarationHaveABody()) {
+ InsertLoc = Method->getBody()->getLocStart();
+ }
+
+ if (!InsertLoc.isValid()) {
+ if (Tokens.size() > 2 && GetText(Tokens.back(), Sources) == "0" &&
+ GetText(Tokens[Tokens.size() - 2], Sources) == "=") {
+ InsertLoc = Tokens[Tokens.size() - 2].getLocation();
+ } else if (GetText(Tokens.back(), Sources) == "ABSTRACT") {
+ InsertLoc = Tokens.back().getLocation();
+ }
+ }
+
+ if (!InsertLoc.isValid()) {
+ InsertLoc = FileRange.getEnd();
+ ReplacementText = " override";
+ }
+ Diag << FixItHint::CreateInsertion(InsertLoc, ReplacementText);
+ }
+
+ if (Method->isVirtualAsWritten()) {
+ for (unsigned i = 0, e = Tokens.size(); i != e; ++i) {
+ if (Tokens[i].is(tok::raw_identifier) &&
+ GetText(Tokens[i], Sources) == "virtual") {
+ Diag << FixItHint::CreateRemoval(CharSourceRange::getTokenRange(
+ Tokens[i].getLocation(), Tokens[i].getLocation()));
+ break;
+ }
+ }
+ }
+}
+
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tools-extra/clang-tidy/misc/UseOverride.h b/clang-tools-extra/clang-tidy/misc/UseOverride.h
new file mode 100644
index 00000000000..0f911771daa
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/misc/UseOverride.h
@@ -0,0 +1,29 @@
+//===--- UseOverride.h - clang-tidy -----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_USE_OVERRIDE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_USE_OVERRIDE_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+
+/// \brief Use C++11's 'override' and remove 'virtual' where applicable.
+class UseOverride : public ClangTidyCheck {
+public:
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_USE_OVERRIDE_H
+
OpenPOWER on IntegriCloud