diff options
author | Julie Hockett <juliehockett@google.com> | 2018-05-11 21:08:59 +0000 |
---|---|---|
committer | Julie Hockett <juliehockett@google.com> | 2018-05-11 21:08:59 +0000 |
commit | f108a8fee10fb189faff4b2edbecbec8b6322a58 (patch) | |
tree | 2aff4c3438817a39992396a6db4dc983870e0b55 /clang-tools-extra/clang-tidy | |
parent | 66a0b774937a616ee9f6dac4015263f8f7c83fc0 (diff) | |
download | bcm5719-llvm-f108a8fee10fb189faff4b2edbecbec8b6322a58.tar.gz bcm5719-llvm-f108a8fee10fb189faff4b2edbecbec8b6322a58.zip |
Reland "[clang-tidy] Adding RestrictSystemIncludes check to Fuchsia module"
This relands r332125 with a fixed test.
llvm-svn: 332141
Diffstat (limited to 'clang-tools-extra/clang-tidy')
4 files changed, 170 insertions, 0 deletions
diff --git a/clang-tools-extra/clang-tidy/fuchsia/CMakeLists.txt b/clang-tools-extra/clang-tidy/fuchsia/CMakeLists.txt index c2ed2524906..b69a5c06470 100644 --- a/clang-tools-extra/clang-tidy/fuchsia/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/fuchsia/CMakeLists.txt @@ -5,6 +5,7 @@ add_clang_library(clangTidyFuchsiaModule FuchsiaTidyModule.cpp MultipleInheritanceCheck.cpp OverloadedOperatorCheck.cpp + RestrictSystemIncludesCheck.cpp StaticallyConstructedObjectsCheck.cpp TrailingReturnCheck.cpp VirtualInheritanceCheck.cpp diff --git a/clang-tools-extra/clang-tidy/fuchsia/FuchsiaTidyModule.cpp b/clang-tools-extra/clang-tidy/fuchsia/FuchsiaTidyModule.cpp index 67b3bc91347..0d3bbfe7475 100644 --- a/clang-tools-extra/clang-tidy/fuchsia/FuchsiaTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/fuchsia/FuchsiaTidyModule.cpp @@ -14,6 +14,7 @@ #include "DefaultArgumentsCheck.h" #include "MultipleInheritanceCheck.h" #include "OverloadedOperatorCheck.h" +#include "RestrictSystemIncludesCheck.h" #include "StaticallyConstructedObjectsCheck.h" #include "TrailingReturnCheck.h" #include "VirtualInheritanceCheck.h" @@ -36,6 +37,8 @@ public: "fuchsia-multiple-inheritance"); CheckFactories.registerCheck<OverloadedOperatorCheck>( "fuchsia-overloaded-operator"); + CheckFactories.registerCheck<RestrictSystemIncludesCheck>( + "fuchsia-restrict-system-includes"); CheckFactories.registerCheck<StaticallyConstructedObjectsCheck>( "fuchsia-statically-constructed-objects"); CheckFactories.registerCheck<TrailingReturnCheck>( diff --git a/clang-tools-extra/clang-tidy/fuchsia/RestrictSystemIncludesCheck.cpp b/clang-tools-extra/clang-tidy/fuchsia/RestrictSystemIncludesCheck.cpp new file mode 100644 index 00000000000..4817e904105 --- /dev/null +++ b/clang-tools-extra/clang-tidy/fuchsia/RestrictSystemIncludesCheck.cpp @@ -0,0 +1,118 @@ +//===--- RestrictSystemIncludesCheck.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 "RestrictSystemIncludesCheck.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Lex/HeaderSearch.h" +#include "clang/Lex/PPCallbacks.h" +#include "clang/Lex/Preprocessor.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Path.h" +#include <cstring> + +namespace clang { +namespace tidy { +namespace fuchsia { + +class RestrictedIncludesPPCallbacks : public PPCallbacks { +public: + explicit RestrictedIncludesPPCallbacks(RestrictSystemIncludesCheck &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, + SrcMgr::CharacteristicKind FileType) override; + void EndOfMainFile() override; + +private: + struct IncludeDirective { + IncludeDirective() = default; + IncludeDirective(SourceLocation Loc, CharSourceRange Range, + StringRef Filename, StringRef FullPath, bool IsInMainFile) + : Loc(Loc), Range(Range), IncludeFile(Filename), IncludePath(FullPath), + IsInMainFile(IsInMainFile) {} + + SourceLocation Loc; // '#' location in the include directive + CharSourceRange Range; // SourceRange for the file name + std::string IncludeFile; // Filename as a string + std::string IncludePath; // Full file path as a string + bool IsInMainFile; // Whether or not the include is in the main file + }; + + using FileIncludes = llvm::SmallVector<IncludeDirective, 8>; + llvm::SmallDenseMap<FileID, FileIncludes> IncludeDirectives; + + RestrictSystemIncludesCheck &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, + SrcMgr::CharacteristicKind FileType) { + if (!Check.contains(FileName) && SrcMgr::isSystem(FileType)) { + SmallString<256> FullPath; + llvm::sys::path::append(FullPath, SearchPath); + llvm::sys::path::append(FullPath, RelativePath); + // Bucket the allowed include directives by the id of the file they were + // declared in. + IncludeDirectives[SM.getFileID(HashLoc)].emplace_back( + HashLoc, FilenameRange, FileName, FullPath.str(), + SM.isInMainFile(HashLoc)); + } +} + +void RestrictedIncludesPPCallbacks::EndOfMainFile() { + for (const auto &Bucket : IncludeDirectives) { + const FileIncludes &FileDirectives = Bucket.second; + + // Emit fixits for all restricted includes. + for (const auto &Include : FileDirectives) { + // 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.Loc), "\n") + 1; + CharSourceRange ToRange = CharSourceRange::getCharRange( + Include.Loc, Include.Loc.getLocWithOffset(ToLen)); + + if (!Include.IsInMainFile) { + auto D = Check.diag( + Include.Loc, + "system include %0 not allowed, transitively included from %1"); + D << Include.IncludeFile << SM.getFilename(Include.Loc); + D << FixItHint::CreateRemoval(ToRange); + continue; + } + auto D = Check.diag(Include.Loc, "system include %0 not allowed"); + D << Include.IncludeFile; + D << FixItHint::CreateRemoval(ToRange); + } + } +} + +void RestrictSystemIncludesCheck::registerPPCallbacks( + CompilerInstance &Compiler) { + Compiler.getPreprocessor().addPPCallbacks( + llvm::make_unique<RestrictedIncludesPPCallbacks>( + *this, Compiler.getSourceManager())); +} + +void RestrictSystemIncludesCheck::storeOptions( + ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, "Includes", AllowedIncludes); +} + +} // namespace fuchsia +} // namespace tidy +} // namespace clang diff --git a/clang-tools-extra/clang-tidy/fuchsia/RestrictSystemIncludesCheck.h b/clang-tools-extra/clang-tidy/fuchsia/RestrictSystemIncludesCheck.h new file mode 100644 index 00000000000..d4e5ac1e79f --- /dev/null +++ b/clang-tools-extra/clang-tidy/fuchsia/RestrictSystemIncludesCheck.h @@ -0,0 +1,48 @@ +//===--- RestrictSystemIncludesCheck.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_RESTRICTINCLUDESSCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FUCHSIA_RESTRICTINCLUDESSCHECK_H + +#include "../ClangTidy.h" +#include "../ClangTidyDiagnosticConsumer.h" +#include "../utils/OptionsUtils.h" + +namespace clang { +namespace tidy { +namespace fuchsia { + +/// Checks for allowed includes and suggests removal of any others. If no +/// includes are specified, the check will exit without issuing any warnings. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/fuchsia-restrict-system-includes.html +class RestrictSystemIncludesCheck : public ClangTidyCheck { +public: + RestrictSystemIncludesCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context), + AllowedIncludes(Options.get("Includes", "*")), + AllowedIncludesGlobList(AllowedIncludes) {} + + void registerPPCallbacks(CompilerInstance &Compiler) override; + void storeOptions(ClangTidyOptions::OptionMap &Opts) override; + bool contains(StringRef FileName) { + return AllowedIncludesGlobList.contains(FileName); + } + +private: + std::string AllowedIncludes; + GlobList AllowedIncludesGlobList; +}; + +} // namespace fuchsia +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FUCHSIA_RESTRICTINCLUDESSCHECK_H |