juliehockett created this revision.
juliehockett added reviewers: aaron.ballman, hokein, ilya-biryukov.
juliehockett added a project: clang-tools-extra.
Herald added subscribers: xazax.hun, mgorny.

Adding a check to restrict specific includes. Given a list of includes that 
should not be used, the check issues a fixit to remove any include on that list 
from the source file.


https://reviews.llvm.org/D43778

Files:
  clang-tidy/fuchsia/CMakeLists.txt
  clang-tidy/fuchsia/FuchsiaTidyModule.cpp
  clang-tidy/fuchsia/RestrictIncludesCheck.cpp
  clang-tidy/fuchsia/RestrictIncludesCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/fuchsia-restrict-includes.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/fuchsia-restrict-includes.cpp

Index: test/clang-tidy/fuchsia-restrict-includes.cpp
===================================================================
--- /dev/null
+++ test/clang-tidy/fuchsia-restrict-includes.cpp
@@ -0,0 +1,13 @@
+// RUN: %check_clang_tidy %s fuchsia-restrict-includes %t \
+// RUN:		-config="{CheckOptions: [{key: fuchsia-restrict-includes.Includes, value: 'b.h;s.h;'}]}" \
+// RUN:   -- -std=c++11 -I %S/Inputs/Headers -isystem %S/Inputs/Headers
+
+#include "a.h"
+#include "b.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: Restricted include found.
+// CHECK-FIXES-NOT: #include "b.h"
+
+#include <i.h>
+#include <s.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: Restricted include found.
+// CHECK-FIXES-NOT: #include <s.h>
Index: docs/clang-tidy/checks/list.rst
===================================================================
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -74,6 +74,7 @@
    fuchsia-default-arguments
    fuchsia-multiple-inheritance
    fuchsia-overloaded-operator
+   fuchsia-restrict-includes
    fuchsia-statically-constructed-objects
    fuchsia-trailing-return
    fuchsia-virtual-inheritance
Index: docs/clang-tidy/checks/fuchsia-restrict-includes.rst
===================================================================
--- /dev/null
+++ docs/clang-tidy/checks/fuchsia-restrict-includes.rst
@@ -0,0 +1,27 @@
+.. title:: clang-tidy - fuchsia-restrict-includes
+
+fuchsia-restrict-includes
+=========================
+
+Checks for restricted headers and suggests their removal.
+
+For example, given the restricted include name 'a.h', if either:
+
+.. code-block:: c++
+
+  #include "a.h"
+
+or
+
+.. code-block:: c++
+
+  #include <a.h>
+
+appears, the fix would suggest its removal. 
+  
+Options
+-------
+
+.. option:: Includes
+
+   A string containing a comma-separated list of header filenames to restrict. Default is an empty string.
Index: docs/ReleaseNotes.rst
===================================================================
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -75,6 +75,11 @@
 
   Warns if a class inherits from multiple classes that are not pure virtual.
 
+- New `fuchsia-restrict-includes
+  <http://clang.llvm.org/extra/clang-tidy/checks/fuchsia-restrict-includes.html>`_ check
+
+  Checks for restricted headers and suggests their removal.
+
 - New `fuchsia-statically-constructed-objects
   <http://clang.llvm.org/extra/clang-tidy/checks/fuchsia-statically-constructed-objects.html>`_ check
 
Index: clang-tidy/fuchsia/RestrictIncludesCheck.h
===================================================================
--- /dev/null
+++ clang-tidy/fuchsia/RestrictIncludesCheck.h
@@ -0,0 +1,44 @@
+//===--- RestrictIncludesCheck.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_RESTRICTHEADERSCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FUCHSIA_RESTRICTHEADERSCHECK_H
+
+#include "../ClangTidy.h"
+#include "../utils/OptionsUtils.h"
+
+namespace clang {
+namespace tidy {
+namespace fuchsia {
+
+/// Checks for restricted headers and suggests their removal.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/fuchsia-restrict-includes.html
+class RestrictIncludesCheck : public ClangTidyCheck {
+ public:
+  RestrictIncludesCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context),
+        RestrictedIncludes(utils::options::parseStringList(
+            Options.get("Includes", "::std::vector"))) {}
+  void registerPPCallbacks(CompilerInstance &Compiler) override;
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+  std::vector<std::string> &getRestrictedIncludes() {
+    return RestrictedIncludes;
+  }
+
+ private:
+  std::vector<std::string> RestrictedIncludes;
+};
+
+}  // namespace fuchsia
+}  // namespace tidy
+}  // namespace clang
+
+#endif  // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FUCHSIA_RESTRICTHEADERSCHECK_H
Index: clang-tidy/fuchsia/RestrictIncludesCheck.cpp
===================================================================
--- /dev/null
+++ clang-tidy/fuchsia/RestrictIncludesCheck.cpp
@@ -0,0 +1,112 @@
+//===--- RestrictIncludesCheck.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 "RestrictIncludesCheck.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/Preprocessor.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace fuchsia {
+
+class RestrictedIncludesPPCallbacks : public PPCallbacks {
+ public:
+  explicit RestrictedIncludesPPCallbacks(RestrictIncludesCheck &Check,
+                                         SourceManager &SM)
+      : Check(Check), SM(SM) {}
+
+  void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
+                          StringRef FileName, bool IsAngled,
+                          CharSourceRange FilenameRange, const FileEntry *File,
+                          StringRef SearchPath, StringRef RelativePath,
+                          const Module *Imported) override;
+  void EndOfMainFile() override;
+
+ private:
+  struct IncludeDirective {
+    IncludeDirective() = default;
+    IncludeDirective(SourceLocation Loc_, CharSourceRange Range_,
+                     StringRef Filename_)
+        : Loc(Loc_), Range(Range_), Filename(Filename_) {}
+
+    SourceLocation Loc;     ///< '#' location in the include directive
+    CharSourceRange Range;  ///< SourceRange for the file name
+    std::string Filename;   ///< Filename as a string
+  };
+
+  bool isRestricted(StringRef Filename) const;
+
+  typedef std::vector<IncludeDirective> FileIncludes;
+  std::map<clang::FileID, FileIncludes> IncludeDirectives;
+
+  RestrictIncludesCheck &Check;
+  SourceManager &SM;
+};
+
+void RestrictedIncludesPPCallbacks::InclusionDirective(
+    SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName,
+    bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File,
+    StringRef SearchPath, StringRef RelativePath, const Module *Imported) {
+  if (isRestricted(FileName))
+    // Bucket the restricted include directives by the id of the file they were
+    // declared in.
+    IncludeDirectives[SM.getFileID(HashLoc)].emplace_back(
+        HashLoc, FilenameRange, FileName);
+}
+
+void RestrictedIncludesPPCallbacks::EndOfMainFile() {
+  if (IncludeDirectives.empty()) return;
+
+  for (auto &Bucket : IncludeDirectives) {
+    auto &FileDirectives = Bucket.second;
+
+    // Emit fixits for all restricted includes.
+    for (const auto &Include : FileDirectives) {
+      // Emit a warning.
+      auto D = Check.diag(Include.Loc, "Restricted include found.");
+
+      // Fetch the length of the include statement from the start to just after
+      // the newline, for finding the end (including the newline).
+      unsigned ToLen =
+          std::strcspn(SM.getCharacterData(Include.Range.getBegin()), "\n") + 1;
+      auto ToRange = CharSourceRange::getCharRange(
+          Include.Loc, ToLoc.getLocWithOffset(ToLen));
+
+      D << FixItHint::CreateRemoval(ToRange);
+    }
+  }
+
+  IncludeDirectives.clear();
+}
+
+/// Check if a given include is in the restricted list of includes.
+bool RestrictedIncludesPPCallbacks::isRestricted(StringRef IncludeFile) const {
+  for (const auto &Include : Check.getRestrictedIncludes()) {
+    if (IncludeFile == Include) return true;
+  }
+  return false;
+}
+
+void RestrictIncludesCheck::registerPPCallbacks(CompilerInstance &Compiler) {
+  Compiler.getPreprocessor().addPPCallbacks(
+      ::llvm::make_unique<RestrictedIncludesPPCallbacks>(
+          *this, Compiler.getSourceManager()));
+}
+
+void RestrictIncludesCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "Includes",
+                utils::options::serializeStringList(RestrictedIncludes));
+}
+
+}  // namespace fuchsia
+}  // namespace tidy
+}  // namespace clang
Index: clang-tidy/fuchsia/FuchsiaTidyModule.cpp
===================================================================
--- clang-tidy/fuchsia/FuchsiaTidyModule.cpp
+++ clang-tidy/fuchsia/FuchsiaTidyModule.cpp
@@ -13,6 +13,7 @@
 #include "DefaultArgumentsCheck.h"
 #include "MultipleInheritanceCheck.h"
 #include "OverloadedOperatorCheck.h"
+#include "RestrictIncludesCheck.h"
 #include "StaticallyConstructedObjectsCheck.h"
 #include "TrailingReturnCheck.h"
 #include "VirtualInheritanceCheck.h"
@@ -33,6 +34,8 @@
         "fuchsia-multiple-inheritance");
     CheckFactories.registerCheck<OverloadedOperatorCheck>(
         "fuchsia-overloaded-operator");
+    CheckFactories.registerCheck<RestrictIncludesCheck>(
+        "fuchsia-restrict-includes");
     CheckFactories.registerCheck<StaticallyConstructedObjectsCheck>(
         "fuchsia-statically-constructed-objects");
     CheckFactories.registerCheck<TrailingReturnCheck>(
Index: clang-tidy/fuchsia/CMakeLists.txt
===================================================================
--- clang-tidy/fuchsia/CMakeLists.txt
+++ clang-tidy/fuchsia/CMakeLists.txt
@@ -5,6 +5,7 @@
   FuchsiaTidyModule.cpp
   MultipleInheritanceCheck.cpp
   OverloadedOperatorCheck.cpp
+  RestrictIncludesCheck.cpp
   StaticallyConstructedObjectsCheck.cpp
   TrailingReturnCheck.cpp
   VirtualInheritanceCheck.cpp
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to