DennisMelamed created this revision.
DennisMelamed added reviewers: alexfh, aaron.ballman, hokein, JonasToth.
Herald added subscribers: xazax.hun, mgorny.

[clang-tidy] Flag Classes Inheriting From Structs

Added a check which flags cases of a class inheriting from a struct, which can 
cause unintended scope issues since struct members are public by default.

Patch by Dennis Melamed


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D52552

Files:
  clang-tidy/misc/CMakeLists.txt
  clang-tidy/misc/ClassInheritFromStructCheck.cpp
  clang-tidy/misc/ClassInheritFromStructCheck.h
  clang-tidy/misc/MiscTidyModule.cpp
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/misc-class-inherit-from-struct.rst
  test/clang-tidy/misc-class-inherit-from-struct.cpp

Index: test/clang-tidy/misc-class-inherit-from-struct.cpp
===================================================================
--- /dev/null
+++ test/clang-tidy/misc-class-inherit-from-struct.cpp
@@ -0,0 +1,22 @@
+// RUN: %check_clang_tidy %s misc-class-inherit-from-struct %t
+
+struct A
+{
+    int a;
+};
+
+class B:A
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: classes should not inherit from structs [misc-class-inherit-from-struct]
+{
+    int b;
+};
+
+class C
+{
+    int c;
+};
+
+class D:C
+{
+    int d;
+};
Index: docs/clang-tidy/checks/misc-class-inherit-from-struct.rst
===================================================================
--- /dev/null
+++ docs/clang-tidy/checks/misc-class-inherit-from-struct.rst
@@ -0,0 +1,18 @@
+.. title:: clang-tidy - misc-class-inherit-from-struct
+
+misc-class-inherit-from-struct
+==============================
+
+Finds instances of classes inheriting from structs. Structs are meant for 
+storing data and are often used to maintain C compatibility. Having a class
+inherit from them can lead to confusion with what type of object is being 
+dealt with. Additionally, the default public nature of struct members can 
+lead to unintentional exposure of members.
+
+.. code-block:: c++
+  
+  struct A {};
+  class B: public A {}; //throws an error, members of A might be
+                        //unintentionally exposed
+  class C {};
+  class D: public C {}; //fine
Index: docs/clang-tidy/checks/list.rst
===================================================================
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -159,6 +159,7 @@
    llvm-include-order
    llvm-namespace-comment
    llvm-twine-local
+   misc-class-inherit-from-struct
    misc-definitions-in-headers
    misc-misplaced-const
    misc-new-delete-overloads
Index: docs/ReleaseNotes.rst
===================================================================
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -106,6 +106,13 @@
   Detects usage of magic numbers, numbers that are used as literals instead of
   introduced via constants or symbols.
 
+- New :doc:`misc-class-inherit-from-struct
+  <clang-tidy/checks/misc-class-inherit-from-struct>` check.
+
+  Detects instances of classes inheriting from structs as that might lead to
+  unintended member access issues.
+
+
 Improvements to include-fixer
 -----------------------------
 
Index: clang-tidy/misc/MiscTidyModule.cpp
===================================================================
--- clang-tidy/misc/MiscTidyModule.cpp
+++ clang-tidy/misc/MiscTidyModule.cpp
@@ -10,6 +10,7 @@
 #include "../ClangTidy.h"
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
+#include "ClassInheritFromStructCheck.h"
 #include "DefinitionsInHeadersCheck.h"
 #include "MisplacedConstCheck.h"
 #include "NewDeleteOverloadsCheck.h"
@@ -30,6 +31,8 @@
 class MiscModule : public ClangTidyModule {
 public:
   void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+    CheckFactories.registerCheck<ClassInheritFromStructCheck>(
+        "misc-class-inherit-from-struct");
     CheckFactories.registerCheck<DefinitionsInHeadersCheck>(
         "misc-definitions-in-headers");
     CheckFactories.registerCheck<MisplacedConstCheck>("misc-misplaced-const");
Index: clang-tidy/misc/ClassInheritFromStructCheck.h
===================================================================
--- /dev/null
+++ clang-tidy/misc/ClassInheritFromStructCheck.h
@@ -0,0 +1,35 @@
+//===--- ClassInheritFromStructCheck.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_CLASSINHERITFROMSTRUCTCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_CLASSINHERITFROMSTRUCTCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+/// Matches non-implicit classes which inherit from structs
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/misc-class-inherit-from-struct.html
+class ClassInheritFromStructCheck : public ClangTidyCheck {
+public:
+  ClassInheritFromStructCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_CLASSINHERITFROMSTRUCTCHECK_H
Index: clang-tidy/misc/ClassInheritFromStructCheck.cpp
===================================================================
--- /dev/null
+++ clang-tidy/misc/ClassInheritFromStructCheck.cpp
@@ -0,0 +1,31 @@
+//===--- ClassInheritFromStructCheck.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 "ClassInheritFromStructCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+void ClassInheritFromStructCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(cxxRecordDecl(isClass(),unless(isImplicit()),isDerivedFrom(cxxRecordDecl(isStruct()))).bind("class"), this);
+}
+
+void ClassInheritFromStructCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *MatchedDecl = Result.Nodes.getNodeAs<CXXRecordDecl>("class");
+  diag(MatchedDecl->getLocation(), "classes should not inherit from structs");
+}
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
Index: clang-tidy/misc/CMakeLists.txt
===================================================================
--- clang-tidy/misc/CMakeLists.txt
+++ clang-tidy/misc/CMakeLists.txt
@@ -1,6 +1,7 @@
 set(LLVM_LINK_COMPONENTS support)
 
 add_clang_library(clangTidyMiscModule
+  ClassInheritFromStructCheck.cpp
   DefinitionsInHeadersCheck.cpp
   MiscTidyModule.cpp
   MisplacedConstCheck.cpp
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to