aboutsummaryrefslogtreecommitdiff
path: root/clang-tidy/readability
diff options
context:
space:
mode:
authorGabor Horvath <xazax.hun@gmail.com>2017-08-08 15:33:48 +0000
committerGabor Horvath <xazax.hun@gmail.com>2017-08-08 15:33:48 +0000
commit8ec8591e4b75899a1d1dd3dd95482d57cc199357 (patch)
treee608039d60d891145fb42435e6575fdaae3e1249 /clang-tidy/readability
parent227f1ffb94cc42302698e9b1199f378000d2287f (diff)
[clang-tidy] Add new readability non-idiomatic static access check
Patch by: Lilla Barancsuk Differential Revision: https://reviews.llvm.org/D35937 git-svn-id: https://llvm.org/svn/llvm-project/clang-tools-extra/trunk@310371 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'clang-tidy/readability')
-rw-r--r--clang-tidy/readability/CMakeLists.txt1
-rw-r--r--clang-tidy/readability/ReadabilityTidyModule.cpp3
-rw-r--r--clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp90
-rw-r--r--clang-tidy/readability/StaticAccessedThroughInstanceCheck.h43
4 files changed, 137 insertions, 0 deletions
diff --git a/clang-tidy/readability/CMakeLists.txt b/clang-tidy/readability/CMakeLists.txt
index 8e6c6581..a130c9b4 100644
--- a/clang-tidy/readability/CMakeLists.txt
+++ b/clang-tidy/readability/CMakeLists.txt
@@ -25,6 +25,7 @@ add_clang_library(clangTidyReadabilityModule
RedundantSmartptrGetCheck.cpp
RedundantStringInitCheck.cpp
SimplifyBooleanExprCheck.cpp
+ StaticAccessedThroughInstanceCheck.cpp
StaticDefinitionInAnonymousNamespaceCheck.cpp
UniqueptrDeleteReleaseCheck.cpp
diff --git a/clang-tidy/readability/ReadabilityTidyModule.cpp b/clang-tidy/readability/ReadabilityTidyModule.cpp
index 81a9d6f3..395730dd 100644
--- a/clang-tidy/readability/ReadabilityTidyModule.cpp
+++ b/clang-tidy/readability/ReadabilityTidyModule.cpp
@@ -32,6 +32,7 @@
#include "RedundantStringCStrCheck.h"
#include "RedundantStringInitCheck.h"
#include "SimplifyBooleanExprCheck.h"
+#include "StaticAccessedThroughInstanceCheck.h"
#include "StaticDefinitionInAnonymousNamespaceCheck.h"
#include "UniqueptrDeleteReleaseCheck.h"
@@ -70,6 +71,8 @@ public:
"readability-redundant-function-ptr-dereference");
CheckFactories.registerCheck<RedundantMemberInitCheck>(
"readability-redundant-member-init");
+ CheckFactories.registerCheck<StaticAccessedThroughInstanceCheck>(
+ "readability-static-accessed-through-instance");
CheckFactories.registerCheck<StaticDefinitionInAnonymousNamespaceCheck>(
"readability-static-definition-in-anonymous-namespace");
CheckFactories.registerCheck<readability::NamedParameterCheck>(
diff --git a/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp b/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp
new file mode 100644
index 00000000..b1365772
--- /dev/null
+++ b/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp
@@ -0,0 +1,90 @@
+//===--- StaticAccessedThroughInstanceCheck.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 "StaticAccessedThroughInstanceCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+static unsigned getNameSpecifierNestingLevel(const QualType &QType) {
+ if (const ElaboratedType *ElType = QType->getAs<ElaboratedType>()) {
+ const NestedNameSpecifier *NestedSpecifiers = ElType->getQualifier();
+ unsigned NameSpecifierNestingLevel = 1;
+ do {
+ NameSpecifierNestingLevel++;
+ NestedSpecifiers = NestedSpecifiers->getPrefix();
+ } while (NestedSpecifiers);
+
+ return NameSpecifierNestingLevel;
+ }
+ return 0;
+}
+
+void StaticAccessedThroughInstanceCheck::storeOptions(
+ ClangTidyOptions::OptionMap &Opts) {
+ Options.store(Opts, "NameSpecifierNestingThreshold",
+ NameSpecifierNestingThreshold);
+}
+
+void StaticAccessedThroughInstanceCheck::registerMatchers(MatchFinder *Finder) {
+ Finder->addMatcher(
+ memberExpr(hasDeclaration(anyOf(cxxMethodDecl(isStaticStorageClass()),
+ varDecl(hasStaticStorageDuration()))),
+ unless(isInTemplateInstantiation()))
+ .bind("memberExpression"),
+ this);
+}
+
+void StaticAccessedThroughInstanceCheck::check(
+ const MatchFinder::MatchResult &Result) {
+ const auto *MemberExpression =
+ Result.Nodes.getNodeAs<MemberExpr>("memberExpression");
+
+ if (MemberExpression->getLocStart().isMacroID())
+ return;
+
+ const Expr *BaseExpr = MemberExpression->getBase();
+
+ // Do not warn for overlaoded -> operators.
+ if (isa<CXXOperatorCallExpr>(BaseExpr))
+ return;
+
+ QualType BaseType =
+ BaseExpr->getType()->isPointerType()
+ ? BaseExpr->getType()->getPointeeType().getUnqualifiedType()
+ : BaseExpr->getType().getUnqualifiedType();
+
+ const ASTContext *AstContext = Result.Context;
+ PrintingPolicy PrintingPolicyWithSupressedTag(AstContext->getLangOpts());
+ PrintingPolicyWithSupressedTag.SuppressTagKeyword = true;
+ std::string BaseTypeName =
+ BaseType.getAsString(PrintingPolicyWithSupressedTag);
+
+ SourceLocation MemberExprStartLoc = MemberExpression->getLocStart();
+ auto Diag =
+ diag(MemberExprStartLoc, "static member accessed through instance");
+
+ if (BaseExpr->HasSideEffects(*AstContext) ||
+ getNameSpecifierNestingLevel(BaseType) > NameSpecifierNestingThreshold)
+ return;
+
+ Diag << FixItHint::CreateReplacement(
+ CharSourceRange::getCharRange(MemberExprStartLoc,
+ MemberExpression->getMemberLoc()),
+ BaseTypeName + "::");
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/readability/StaticAccessedThroughInstanceCheck.h b/clang-tidy/readability/StaticAccessedThroughInstanceCheck.h
new file mode 100644
index 00000000..c2eebabe
--- /dev/null
+++ b/clang-tidy/readability/StaticAccessedThroughInstanceCheck.h
@@ -0,0 +1,43 @@
+//===--- StaticAccessedThroughInstanceCheck.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_READABILITY_STATIC_ACCESSED_THROUGH_INSTANCE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_STATIC_ACCESSED_THROUGH_INSTANCE_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// \@brief Checks for member expressions that access static members through
+/// instances and replaces them with uses of the appropriate qualified-id.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/readability-static-accessed-through-instance.html
+class StaticAccessedThroughInstanceCheck : public ClangTidyCheck {
+public:
+ StaticAccessedThroughInstanceCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context),
+ NameSpecifierNestingThreshold(
+ Options.get("NameSpecifierNestingThreshold", 3)) {}
+
+ void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+ const unsigned NameSpecifierNestingThreshold;
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_STATIC_ACCESSED_THROUGH_INSTANCE_H