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
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits