[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
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 0000000..6f3b433
--- /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<CXXRecordDecl>("decl"))
+    diag(D->getLocStart(), "direct virtual inheritance is disallowed");
+}
+
+}  // namespace fuchsia
+}  // namespace tidy
+}  // namespace clang