ArgumentsAdjusters.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. //===- ArgumentsAdjusters.cpp - Command line arguments adjuster -----------===//
  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. //
  9. // This file contains definitions of classes which implement ArgumentsAdjuster
  10. // interface.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "clang/Tooling/ArgumentsAdjusters.h"
  14. #include "clang/Basic/LLVM.h"
  15. #include "llvm/ADT/STLExtras.h"
  16. #include "llvm/ADT/StringRef.h"
  17. #include <cstddef>
  18. #include <vector>
  19. namespace clang {
  20. namespace tooling {
  21. static StringRef getDriverMode(const CommandLineArguments &Args) {
  22. for (const auto &Arg : Args) {
  23. StringRef ArgRef = Arg;
  24. if (ArgRef.consume_front("--driver-mode=")) {
  25. return ArgRef;
  26. }
  27. }
  28. return StringRef();
  29. }
  30. /// Add -fsyntax-only option and drop options that triggers output generation.
  31. ArgumentsAdjuster getClangSyntaxOnlyAdjuster() {
  32. return [](const CommandLineArguments &Args, StringRef /*unused*/) {
  33. CommandLineArguments AdjustedArgs;
  34. bool HasSyntaxOnly = false;
  35. constexpr llvm::StringRef OutputCommands[] = {
  36. // FIXME: Add other options that generate output.
  37. "-save-temps",
  38. "--save-temps",
  39. };
  40. for (size_t i = 0, e = Args.size(); i < e; ++i) {
  41. StringRef Arg = Args[i];
  42. // Skip output commands.
  43. if (llvm::any_of(OutputCommands, [&Arg](llvm::StringRef OutputCommand) {
  44. return Arg.startswith(OutputCommand);
  45. }))
  46. continue;
  47. if (!Arg.startswith("-fcolor-diagnostics") &&
  48. !Arg.startswith("-fdiagnostics-color"))
  49. AdjustedArgs.push_back(Args[i]);
  50. // If we strip a color option, make sure we strip any preceeding `-Xclang`
  51. // option as well.
  52. // FIXME: This should be added to most argument adjusters!
  53. else if (!AdjustedArgs.empty() && AdjustedArgs.back() == "-Xclang")
  54. AdjustedArgs.pop_back();
  55. if (Arg == "-fsyntax-only")
  56. HasSyntaxOnly = true;
  57. }
  58. if (!HasSyntaxOnly)
  59. AdjustedArgs =
  60. getInsertArgumentAdjuster("-fsyntax-only")(AdjustedArgs, "");
  61. return AdjustedArgs;
  62. };
  63. }
  64. ArgumentsAdjuster getClangStripOutputAdjuster() {
  65. return [](const CommandLineArguments &Args, StringRef /*unused*/) {
  66. CommandLineArguments AdjustedArgs;
  67. for (size_t i = 0, e = Args.size(); i < e; ++i) {
  68. StringRef Arg = Args[i];
  69. if (!Arg.startswith("-o"))
  70. AdjustedArgs.push_back(Args[i]);
  71. if (Arg == "-o") {
  72. // Output is specified as -o foo. Skip the next argument too.
  73. ++i;
  74. }
  75. // Else, the output is specified as -ofoo. Just do nothing.
  76. }
  77. return AdjustedArgs;
  78. };
  79. }
  80. ArgumentsAdjuster getClangStripDependencyFileAdjuster() {
  81. return [](const CommandLineArguments &Args, StringRef /*unused*/) {
  82. auto UsingClDriver = (getDriverMode(Args) == "cl");
  83. CommandLineArguments AdjustedArgs;
  84. for (size_t i = 0, e = Args.size(); i < e; ++i) {
  85. StringRef Arg = Args[i];
  86. // These flags take an argument: -MX foo. Skip the next argument also.
  87. if (!UsingClDriver && (Arg == "-MF" || Arg == "-MT" || Arg == "-MQ")) {
  88. ++i;
  89. continue;
  90. }
  91. // When not using the cl driver mode, dependency file generation options
  92. // begin with -M. These include -MM, -MF, -MG, -MP, -MT, -MQ, -MD, and
  93. // -MMD.
  94. if (!UsingClDriver && Arg.startswith("-M"))
  95. continue;
  96. // Under MSVC's cl driver mode, dependency file generation is controlled
  97. // using /showIncludes
  98. if (Arg.startswith("/showIncludes") || Arg.startswith("-showIncludes"))
  99. continue;
  100. AdjustedArgs.push_back(Args[i]);
  101. }
  102. return AdjustedArgs;
  103. };
  104. }
  105. ArgumentsAdjuster getInsertArgumentAdjuster(const CommandLineArguments &Extra,
  106. ArgumentInsertPosition Pos) {
  107. return [Extra, Pos](const CommandLineArguments &Args, StringRef /*unused*/) {
  108. CommandLineArguments Return(Args);
  109. CommandLineArguments::iterator I;
  110. if (Pos == ArgumentInsertPosition::END) {
  111. I = std::find(Return.begin(), Return.end(), "--");
  112. } else {
  113. I = Return.begin();
  114. ++I; // To leave the program name in place
  115. }
  116. Return.insert(I, Extra.begin(), Extra.end());
  117. return Return;
  118. };
  119. }
  120. ArgumentsAdjuster getInsertArgumentAdjuster(const char *Extra,
  121. ArgumentInsertPosition Pos) {
  122. return getInsertArgumentAdjuster(CommandLineArguments(1, Extra), Pos);
  123. }
  124. ArgumentsAdjuster combineAdjusters(ArgumentsAdjuster First,
  125. ArgumentsAdjuster Second) {
  126. if (!First)
  127. return Second;
  128. if (!Second)
  129. return First;
  130. return [First, Second](const CommandLineArguments &Args, StringRef File) {
  131. return Second(First(Args, File), File);
  132. };
  133. }
  134. ArgumentsAdjuster getStripPluginsAdjuster() {
  135. return [](const CommandLineArguments &Args, StringRef /*unused*/) {
  136. CommandLineArguments AdjustedArgs;
  137. for (size_t I = 0, E = Args.size(); I != E; I++) {
  138. // According to https://clang.llvm.org/docs/ClangPlugins.html
  139. // plugin arguments are in the form:
  140. // -Xclang {-load, -plugin, -plugin-arg-<plugin-name>, -add-plugin}
  141. // -Xclang <arbitrary-argument>
  142. if (I + 4 < E && Args[I] == "-Xclang" &&
  143. (Args[I + 1] == "-load" || Args[I + 1] == "-plugin" ||
  144. llvm::StringRef(Args[I + 1]).startswith("-plugin-arg-") ||
  145. Args[I + 1] == "-add-plugin") &&
  146. Args[I + 2] == "-Xclang") {
  147. I += 3;
  148. continue;
  149. }
  150. AdjustedArgs.push_back(Args[I]);
  151. }
  152. return AdjustedArgs;
  153. };
  154. }
  155. } // end namespace tooling
  156. } // end namespace clang