From 63b57db3969109c9f32a7835fdf4da73f8954272 Mon Sep 17 00:00:00 2001 From: Julie Hockett Date: Fri, 15 Dec 2017 18:54:28 +0000 Subject: [PATCH] [clang-tidy] Adding Fuchsia checker for virtual inheritance Adds a check to the Fuchsia module to warn if classes are defined with virtual inheritance. See https://fuchsia.googlesource.com/zircon/+/master/docs/cxx.md for reference. Differential Revision: https://reviews.llvm.org/D40813 llvm-svn: 320841 --- .../clang-tidy/fuchsia/CMakeLists.txt | 1 + .../clang-tidy/fuchsia/FuchsiaTidyModule.cpp | 3 ++ .../fuchsia/VirtualInheritanceCheck.cpp | 41 ++++++++++++++++++ .../fuchsia/VirtualInheritanceCheck.h | 35 ++++++++++++++++ clang-tools-extra/docs/ReleaseNotes.rst | 5 +++ .../checks/fuchsia-virtual-inheritance.rst | 14 +++++++ .../docs/clang-tidy/checks/list.rst | 1 + .../fuchsia-virtual-inheritance.cpp | 42 +++++++++++++++++++ 8 files changed, 142 insertions(+) create mode 100644 clang-tools-extra/clang-tidy/fuchsia/VirtualInheritanceCheck.cpp create mode 100644 clang-tools-extra/clang-tidy/fuchsia/VirtualInheritanceCheck.h create mode 100644 clang-tools-extra/docs/clang-tidy/checks/fuchsia-virtual-inheritance.rst create mode 100644 clang-tools-extra/test/clang-tidy/fuchsia-virtual-inheritance.cpp diff --git a/clang-tools-extra/clang-tidy/fuchsia/CMakeLists.txt b/clang-tools-extra/clang-tidy/fuchsia/CMakeLists.txt index 4a574197cd0c..692a367749e6 100644 --- a/clang-tools-extra/clang-tidy/fuchsia/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/fuchsia/CMakeLists.txt @@ -3,6 +3,7 @@ set(LLVM_LINK_COMPONENTS support) add_clang_library(clangTidyFuchsiaModule DefaultArgumentsCheck.cpp FuchsiaTidyModule.cpp + VirtualInheritanceCheck.cpp LINK_LIBS clangAST diff --git a/clang-tools-extra/clang-tidy/fuchsia/FuchsiaTidyModule.cpp b/clang-tools-extra/clang-tidy/fuchsia/FuchsiaTidyModule.cpp index 708272f9590a..5ed834d956db 100644 --- a/clang-tools-extra/clang-tidy/fuchsia/FuchsiaTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/fuchsia/FuchsiaTidyModule.cpp @@ -11,6 +11,7 @@ #include "../ClangTidyModule.h" #include "../ClangTidyModuleRegistry.h" #include "DefaultArgumentsCheck.h" +#include "VirtualInheritanceCheck.h" using namespace clang::ast_matchers; @@ -24,6 +25,8 @@ public: void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override { CheckFactories.registerCheck( "fuchsia-default-arguments"); + CheckFactories.registerCheck( + "fuchsia-virtual-inheritance"); } }; // Register the FuchsiaTidyModule using this statically initialized variable. diff --git a/clang-tools-extra/clang-tidy/fuchsia/VirtualInheritanceCheck.cpp b/clang-tools-extra/clang-tidy/fuchsia/VirtualInheritanceCheck.cpp new file mode 100644 index 000000000000..6f3b433a7ef0 --- /dev/null +++ b/clang-tools-extra/clang-tidy/fuchsia/VirtualInheritanceCheck.cpp @@ -0,0 +1,41 @@ +//===--- VirtualInheritanceCheck.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 "VirtualInheritanceCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace fuchsia { + +AST_MATCHER(CXXRecordDecl, hasDirectVirtualBaseClass) { + if (!Node.hasDefinition()) return false; + if (!Node.getNumVBases()) return false; + for (const CXXBaseSpecifier &Base : Node.bases()) + if (Base.isVirtual()) return true; + return false; +} + +void VirtualInheritanceCheck::registerMatchers(MatchFinder *Finder) { + // Defining classes using direct virtual inheritance is disallowed. + Finder->addMatcher(cxxRecordDecl(hasDirectVirtualBaseClass()).bind("decl"), + this); +} + +void VirtualInheritanceCheck::check(const MatchFinder::MatchResult &Result) { + if (const auto *D = Result.Nodes.getNodeAs("decl")) + diag(D->getLocStart(), "direct virtual inheritance is disallowed"); +} + +} // namespace fuchsia +} // namespace tidy +} // namespace clang diff --git a/clang-tools-extra/clang-tidy/fuchsia/VirtualInheritanceCheck.h b/clang-tools-extra/clang-tidy/fuchsia/VirtualInheritanceCheck.h new file mode 100644 index 000000000000..b2c84c41119a --- /dev/null +++ b/clang-tools-extra/clang-tidy/fuchsia/VirtualInheritanceCheck.h @@ -0,0 +1,35 @@ +//===--- VirtualInheritanceCheck.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_FUCHSIA_VIRTUAL_INHERITANCE_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FUCHSIA_VIRTUAL_INHERITANCE_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { +namespace fuchsia { + +/// Defining classes with virtual inheritance is disallowed. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/fuchsia-virtual-inheritance.html +class VirtualInheritanceCheck : public ClangTidyCheck { + public: + VirtualInheritanceCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace fuchsia +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FUCHSIA_VIRTUAL_INHERITANCE_H diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index ea312d938879..b8901785b57f 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -134,7 +134,12 @@ Improvements to clang-tidy `_ check Warns if a function or method is declared or called with default arguments. + +- New `fuchsia-virtual-inheritance + `_ check + Warns if classes are defined with virtual inheritance. + - New `google-objc-avoid-throwing-exception `_ check diff --git a/clang-tools-extra/docs/clang-tidy/checks/fuchsia-virtual-inheritance.rst b/clang-tools-extra/docs/clang-tidy/checks/fuchsia-virtual-inheritance.rst new file mode 100644 index 000000000000..f73a49b2b051 --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/fuchsia-virtual-inheritance.rst @@ -0,0 +1,14 @@ +.. title:: clang-tidy - fuchsia-virtual-inheritance + +fuchsia-virtual-inheritance +=========================== + +Warns if classes are defined with virtual inheritance. + +For example, classes should not be defined with virtual inheritance: + +.. code-block:: c++ + + class B : public virtual A {}; // warning + +See the features disallowed in Fuchsia at https://fuchsia.googlesource.com/zircon/+/master/docs/cxx.md diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index 4feaa4905079..e3b0c36c676f 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -69,6 +69,7 @@ Clang-Tidy Checks cppcoreguidelines-slicing cppcoreguidelines-special-member-functions fuchsia-default-arguments + fuchsia-virtual-inheritance google-build-explicit-make-pair google-build-namespaces google-build-using-namespace diff --git a/clang-tools-extra/test/clang-tidy/fuchsia-virtual-inheritance.cpp b/clang-tools-extra/test/clang-tidy/fuchsia-virtual-inheritance.cpp new file mode 100644 index 000000000000..0c3311afcbd9 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/fuchsia-virtual-inheritance.cpp @@ -0,0 +1,42 @@ +// RUN: %check_clang_tidy %s fuchsia-virtual-inheritance %t + +class A { +public: + A(int value) : val(value) {} + + int do_A() { return val; } + +private: + int val; +}; + +class B : public virtual A { + // CHECK-MESSAGES: [[@LINE-1]]:1: warning: direct virtual inheritance is disallowed [fuchsia-virtual-inheritance] + // CHECK-NEXT: class B : public virtual A { +public: + B() : A(0) {} + int do_B() { return 1 + do_A(); } +}; + +class C : public virtual A { + // CHECK-MESSAGES: [[@LINE-1]]:1: warning: direct virtual inheritance is disallowed [fuchsia-virtual-inheritance] + // CHECK-NEXT: class C : public virtual A { +public: + C() : A(0) {} + int do_C() { return 2 + do_A(); } +}; + +class D : public B, public C { +public: + D(int value) : A(value), B(), C() {} + + int do_D() { return do_A() + do_B() + do_C(); } +}; + +int main() { + A *a = new A(0); + B *b = new B(); + C *c = new C(); + D *d = new D(0); + return 0; +}