HeaderAnalysis.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. //===--- HeaderAnalysis.cpp -------------------------------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "clang/Tooling/Inclusions/HeaderAnalysis.h"
  9. #include "clang/Basic/SourceLocation.h"
  10. #include "clang/Lex/HeaderSearch.h"
  11. namespace clang::tooling {
  12. namespace {
  13. // Is Line an #if or #ifdef directive?
  14. // FIXME: This makes headers with #ifdef LINUX/WINDOWS/MACOS marked as non
  15. // self-contained and is probably not what we want.
  16. bool isIf(llvm::StringRef Line) {
  17. Line = Line.ltrim();
  18. if (!Line.consume_front("#"))
  19. return false;
  20. Line = Line.ltrim();
  21. return Line.startswith("if");
  22. }
  23. // Is Line an #error directive mentioning includes?
  24. bool isErrorAboutInclude(llvm::StringRef Line) {
  25. Line = Line.ltrim();
  26. if (!Line.consume_front("#"))
  27. return false;
  28. Line = Line.ltrim();
  29. if (!Line.startswith("error"))
  30. return false;
  31. return Line.contains_insensitive(
  32. "includ"); // Matches "include" or "including".
  33. }
  34. // Heuristically headers that only want to be included via an umbrella.
  35. bool isDontIncludeMeHeader(StringRef Content) {
  36. llvm::StringRef Line;
  37. // Only sniff up to 100 lines or 10KB.
  38. Content = Content.take_front(100 * 100);
  39. for (unsigned I = 0; I < 100 && !Content.empty(); ++I) {
  40. std::tie(Line, Content) = Content.split('\n');
  41. if (isIf(Line) && isErrorAboutInclude(Content.split('\n').first))
  42. return true;
  43. }
  44. return false;
  45. }
  46. bool isImportLine(llvm::StringRef Line) {
  47. Line = Line.ltrim();
  48. if (!Line.consume_front("#"))
  49. return false;
  50. Line = Line.ltrim();
  51. return Line.startswith("import");
  52. }
  53. llvm::StringRef getFileContents(const FileEntry *FE, const SourceManager &SM) {
  54. return const_cast<SourceManager &>(SM)
  55. .getMemoryBufferForFileOrNone(FE)
  56. .value_or(llvm::MemoryBufferRef())
  57. .getBuffer();
  58. }
  59. } // namespace
  60. bool isSelfContainedHeader(const FileEntry *FE, const SourceManager &SM,
  61. HeaderSearch &HeaderInfo) {
  62. assert(FE);
  63. if (!HeaderInfo.isFileMultipleIncludeGuarded(FE) &&
  64. !HeaderInfo.hasFileBeenImported(FE) &&
  65. // Any header that contains #imports is supposed to be #import'd so no
  66. // need to check for anything but the main-file.
  67. (SM.getFileEntryForID(SM.getMainFileID()) != FE ||
  68. !codeContainsImports(getFileContents(FE, SM))))
  69. return false;
  70. // This pattern indicates that a header can't be used without
  71. // particular preprocessor state, usually set up by another header.
  72. return !isDontIncludeMeHeader(getFileContents(FE, SM));
  73. }
  74. bool codeContainsImports(llvm::StringRef Code) {
  75. // Only sniff up to 100 lines or 10KB.
  76. Code = Code.take_front(100 * 100);
  77. llvm::StringRef Line;
  78. for (unsigned I = 0; I < 100 && !Code.empty(); ++I) {
  79. std::tie(Line, Code) = Code.split('\n');
  80. if (isImportLine(Line))
  81. return true;
  82. }
  83. return false;
  84. }
  85. std::optional<StringRef> parseIWYUPragma(const char *Text) {
  86. // Skip the comment start, // or /*.
  87. if (Text[0] != '/' || (Text[1] != '/' && Text[1] != '*'))
  88. return std::nullopt;
  89. bool BlockComment = Text[1] == '*';
  90. Text += 2;
  91. // Per spec, direcitves are whitespace- and case-sensitive.
  92. constexpr llvm::StringLiteral IWYUPragma = " IWYU pragma: ";
  93. if (strncmp(Text, IWYUPragma.data(), IWYUPragma.size()))
  94. return std::nullopt;
  95. Text += IWYUPragma.size();
  96. const char *End = Text;
  97. while (*End != 0 && *End != '\n')
  98. ++End;
  99. StringRef Rest(Text, End - Text);
  100. // Strip off whitespace and comment markers to avoid confusion. This isn't
  101. // fully-compatible with IWYU, which splits into whitespace-delimited tokens.
  102. if (BlockComment)
  103. Rest.consume_back("*/");
  104. return Rest.trim();
  105. }
  106. } // namespace clang::tooling