clang-tools  7.0.0
RestrictSystemIncludesCheck.cpp
Go to the documentation of this file.
1 //===--- RestrictSystemIncludesCheck.cpp - clang-tidy----------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
11 #include "clang/Frontend/CompilerInstance.h"
12 #include "clang/Lex/HeaderSearch.h"
13 #include "clang/Lex/PPCallbacks.h"
14 #include "clang/Lex/Preprocessor.h"
15 #include "llvm/ADT/DenseMap.h"
16 #include "llvm/ADT/SmallVector.h"
17 #include "llvm/Support/Path.h"
18 #include <cstring>
19 
20 namespace clang {
21 namespace tidy {
22 namespace fuchsia {
23 
25 public:
27  SourceManager &SM)
28  : Check(Check), SM(SM) {}
29 
30  void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
31  StringRef FileName, bool IsAngled,
32  CharSourceRange FilenameRange, const FileEntry *File,
33  StringRef SearchPath, StringRef RelativePath,
34  const Module *Imported,
35  SrcMgr::CharacteristicKind FileType) override;
36  void EndOfMainFile() override;
37 
38 private:
39  struct IncludeDirective {
40  IncludeDirective() = default;
41  IncludeDirective(SourceLocation Loc, CharSourceRange Range,
42  StringRef Filename, StringRef FullPath, bool IsInMainFile)
43  : Loc(Loc), Range(Range), IncludeFile(Filename), IncludePath(FullPath),
44  IsInMainFile(IsInMainFile) {}
45 
46  SourceLocation Loc; // '#' location in the include directive
47  CharSourceRange Range; // SourceRange for the file name
48  std::string IncludeFile; // Filename as a string
49  std::string IncludePath; // Full file path as a string
50  bool IsInMainFile; // Whether or not the include is in the main file
51  };
52 
53  using FileIncludes = llvm::SmallVector<IncludeDirective, 8>;
54  llvm::SmallDenseMap<FileID, FileIncludes> IncludeDirectives;
55 
57  SourceManager &SM;
58 };
59 
61  SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName,
62  bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File,
63  StringRef SearchPath, StringRef RelativePath, const Module *Imported,
64  SrcMgr::CharacteristicKind FileType) {
65  if (!Check.contains(FileName) && SrcMgr::isSystem(FileType)) {
66  SmallString<256> FullPath;
67  llvm::sys::path::append(FullPath, SearchPath);
68  llvm::sys::path::append(FullPath, RelativePath);
69  // Bucket the allowed include directives by the id of the file they were
70  // declared in.
71  IncludeDirectives[SM.getFileID(HashLoc)].emplace_back(
72  HashLoc, FilenameRange, FileName, FullPath.str(),
73  SM.isInMainFile(HashLoc));
74  }
75 }
76 
78  for (const auto &Bucket : IncludeDirectives) {
79  const FileIncludes &FileDirectives = Bucket.second;
80 
81  // Emit fixits for all restricted includes.
82  for (const auto &Include : FileDirectives) {
83  // Fetch the length of the include statement from the start to just after
84  // the newline, for finding the end (including the newline).
85  unsigned ToLen = std::strcspn(SM.getCharacterData(Include.Loc), "\n") + 1;
86  CharSourceRange ToRange = CharSourceRange::getCharRange(
87  Include.Loc, Include.Loc.getLocWithOffset(ToLen));
88 
89  if (!Include.IsInMainFile) {
90  auto D = Check.diag(
91  Include.Loc,
92  "system include %0 not allowed, transitively included from %1");
93  D << Include.IncludeFile << SM.getFilename(Include.Loc);
94  D << FixItHint::CreateRemoval(ToRange);
95  continue;
96  }
97  auto D = Check.diag(Include.Loc, "system include %0 not allowed");
98  D << Include.IncludeFile;
99  D << FixItHint::CreateRemoval(ToRange);
100  }
101  }
102 }
103 
105  CompilerInstance &Compiler) {
106  Compiler.getPreprocessor().addPPCallbacks(
107  llvm::make_unique<RestrictedIncludesPPCallbacks>(
108  *this, Compiler.getSourceManager()));
109 }
110 
113  Options.store(Opts, "Includes", AllowedIncludes);
114 }
115 
116 } // namespace fuchsia
117 } // namespace tidy
118 } // namespace clang
SourceLocation Loc
&#39;#&#39; location in the include directive
void storeOptions(ClangTidyOptions::OptionMap &Opts) override
Should store all options supported by this check with their current values or default values for opti...
HeaderHandle File
Checks for allowed includes and suggests removal of any others.
std::string Filename
Filename as a string.
RestrictedIncludesPPCallbacks(RestrictSystemIncludesCheck &Check, SourceManager &SM)
bool IsAngled
true if this was an include with angle brackets
std::map< std::string, std::string > OptionMap
PathRef FileName
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
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
void registerPPCallbacks(CompilerInstance &Compiler) override
Override this to register PPCallbacks with Compiler.
CharSourceRange Range
SourceRange for the file name.