clang  19.0.0git
ArgumentsAdjusters.cpp
Go to the documentation of this file.
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 
15 #include "clang/Basic/LLVM.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/StringRef.h"
18 #include <cstddef>
19 #include <vector>
20 
21 namespace clang {
22 namespace tooling {
23 
24 static StringRef getDriverMode(const CommandLineArguments &Args) {
25  for (const auto &Arg : Args) {
26  StringRef ArgRef = Arg;
27  if (ArgRef.consume_front("--driver-mode=")) {
28  return ArgRef;
29  }
30  }
31  return StringRef();
32 }
33 
34 /// Add -fsyntax-only option and drop options that triggers output generation.
36  return [](const CommandLineArguments &Args, StringRef /*unused*/) {
37  CommandLineArguments AdjustedArgs;
38  bool HasSyntaxOnly = false;
39  constexpr llvm::StringRef OutputCommands[] = {
40  // FIXME: Add other options that generate output.
41  "-save-temps",
42  "--save-temps",
43  };
44  for (size_t i = 0, e = Args.size(); i < e; ++i) {
45  StringRef Arg = Args[i];
46  // Skip output commands.
47  if (llvm::any_of(OutputCommands, [&Arg](llvm::StringRef OutputCommand) {
48  return Arg.starts_with(OutputCommand);
49  }))
50  continue;
51 
52  if (!Arg.starts_with("-fcolor-diagnostics") &&
53  !Arg.starts_with("-fdiagnostics-color"))
54  AdjustedArgs.push_back(Args[i]);
55  // If we strip a color option, make sure we strip any preceeding `-Xclang`
56  // option as well.
57  // FIXME: This should be added to most argument adjusters!
58  else if (!AdjustedArgs.empty() && AdjustedArgs.back() == "-Xclang")
59  AdjustedArgs.pop_back();
60 
61  if (Arg == "-fsyntax-only")
62  HasSyntaxOnly = true;
63  }
64  if (!HasSyntaxOnly)
65  AdjustedArgs =
66  getInsertArgumentAdjuster("-fsyntax-only")(AdjustedArgs, "");
67  return AdjustedArgs;
68  };
69 }
70 
72  return [](const CommandLineArguments &Args, StringRef /*unused*/) {
73  CommandLineArguments AdjustedArgs;
74  for (size_t i = 0, e = Args.size(); i < e; ++i) {
75  StringRef Arg = Args[i];
76  if (!Arg.starts_with("-o"))
77  AdjustedArgs.push_back(Args[i]);
78 
79  if (Arg == "-o") {
80  // Output is specified as -o foo. Skip the next argument too.
81  ++i;
82  }
83  // Else, the output is specified as -ofoo. Just do nothing.
84  }
85  return AdjustedArgs;
86  };
87 }
88 
90  return [](const CommandLineArguments &Args, StringRef /*unused*/) {
91  auto UsingClDriver = (getDriverMode(Args) == "cl");
92 
93  CommandLineArguments AdjustedArgs;
94  for (size_t i = 0, e = Args.size(); i < e; ++i) {
95  StringRef Arg = Args[i];
96 
97  // These flags take an argument: -MX foo. Skip the next argument also.
98  if (!UsingClDriver && (Arg == "-MF" || Arg == "-MT" || Arg == "-MQ")) {
99  ++i;
100  continue;
101  }
102  // When not using the cl driver mode, dependency file generation options
103  // begin with -M. These include -MM, -MF, -MG, -MP, -MT, -MQ, -MD, and
104  // -MMD.
105  if (!UsingClDriver && Arg.starts_with("-M"))
106  continue;
107  // Under MSVC's cl driver mode, dependency file generation is controlled
108  // using /showIncludes
109  if (Arg.starts_with("/showIncludes") || Arg.starts_with("-showIncludes"))
110  continue;
111 
112  AdjustedArgs.push_back(Args[i]);
113  }
114  return AdjustedArgs;
115  };
116 }
117 
120  return [Extra, Pos](const CommandLineArguments &Args, StringRef /*unused*/) {
121  CommandLineArguments Return(Args);
122 
123  CommandLineArguments::iterator I;
124  if (Pos == ArgumentInsertPosition::END) {
125  I = llvm::find(Return, "--");
126  } else {
127  I = Return.begin();
128  ++I; // To leave the program name in place
129  }
130 
131  Return.insert(I, Extra.begin(), Extra.end());
132  return Return;
133  };
134 }
135 
138  return getInsertArgumentAdjuster(CommandLineArguments(1, Extra), Pos);
139 }
140 
142  ArgumentsAdjuster Second) {
143  if (!First)
144  return Second;
145  if (!Second)
146  return First;
147  return [First, Second](const CommandLineArguments &Args, StringRef File) {
148  return Second(First(Args, File), File);
149  };
150 }
151 
153  return [](const CommandLineArguments &Args, StringRef /*unused*/) {
154  CommandLineArguments AdjustedArgs;
155  for (size_t I = 0, E = Args.size(); I != E; I++) {
156  // According to https://clang.llvm.org/docs/ClangPlugins.html
157  // plugin arguments are in the form:
158  // -Xclang {-load, -plugin, -plugin-arg-<plugin-name>, -add-plugin}
159  // -Xclang <arbitrary-argument>
160  if (I + 4 < E && Args[I] == "-Xclang" &&
161  (Args[I + 1] == "-load" || Args[I + 1] == "-plugin" ||
162  llvm::StringRef(Args[I + 1]).starts_with("-plugin-arg-") ||
163  Args[I + 1] == "-add-plugin") &&
164  Args[I + 2] == "-Xclang") {
165  I += 3;
166  continue;
167  }
168  AdjustedArgs.push_back(Args[I]);
169  }
170  return AdjustedArgs;
171  };
172 }
173 
174 } // end namespace tooling
175 } // end namespace clang
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
static StringRef getDriverMode(const CommandLineArguments &Args)
std::vector< std::string > CommandLineArguments
A sequence of command line arguments.
ArgumentsAdjuster getClangSyntaxOnlyAdjuster()
Gets an argument adjuster that converts input command line arguments to the "syntax check only" varia...
ArgumentsAdjuster combineAdjusters(ArgumentsAdjuster First, ArgumentsAdjuster Second)
Gets an argument adjuster which adjusts the arguments in sequence with the First adjuster and then wi...
ArgumentsAdjuster getStripPluginsAdjuster()
Gets an argument adjuster which strips plugin related command line arguments.
ArgumentsAdjuster getClangStripDependencyFileAdjuster()
Gets an argument adjuster which removes dependency-file related command line arguments.
std::function< CommandLineArguments(const CommandLineArguments &, StringRef Filename)> ArgumentsAdjuster
A prototype of a command line adjuster.
ArgumentsAdjuster getInsertArgumentAdjuster(const CommandLineArguments &Extra, ArgumentInsertPosition Pos)
Gets an argument adjuster which inserts Extra arguments in the specified position.
ArgumentsAdjuster getClangStripOutputAdjuster()
Gets an argument adjuster which removes output-related command line arguments.
The JSON file list parser is used to communicate input to InstallAPI.