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