/src/llvm-project/clang/lib/Tooling/ArgumentsAdjusters.cpp
Line | Count | Source (jump to first uncovered line) |
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 | | |
14 | | #include "clang/Tooling/ArgumentsAdjusters.h" |
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 | 0 | static StringRef getDriverMode(const CommandLineArguments &Args) { |
25 | 0 | for (const auto &Arg : Args) { |
26 | 0 | StringRef ArgRef = Arg; |
27 | 0 | if (ArgRef.consume_front("--driver-mode=")) { |
28 | 0 | return ArgRef; |
29 | 0 | } |
30 | 0 | } |
31 | 0 | return StringRef(); |
32 | 0 | } |
33 | | |
34 | | /// Add -fsyntax-only option and drop options that triggers output generation. |
35 | 0 | ArgumentsAdjuster getClangSyntaxOnlyAdjuster() { |
36 | 0 | return [](const CommandLineArguments &Args, StringRef /*unused*/) { |
37 | 0 | CommandLineArguments AdjustedArgs; |
38 | 0 | bool HasSyntaxOnly = false; |
39 | 0 | constexpr llvm::StringRef OutputCommands[] = { |
40 | | // FIXME: Add other options that generate output. |
41 | 0 | "-save-temps", |
42 | 0 | "--save-temps", |
43 | 0 | }; |
44 | 0 | for (size_t i = 0, e = Args.size(); i < e; ++i) { |
45 | 0 | StringRef Arg = Args[i]; |
46 | | // Skip output commands. |
47 | 0 | if (llvm::any_of(OutputCommands, [&Arg](llvm::StringRef OutputCommand) { |
48 | 0 | return Arg.starts_with(OutputCommand); |
49 | 0 | })) |
50 | 0 | continue; |
51 | | |
52 | 0 | if (!Arg.starts_with("-fcolor-diagnostics") && |
53 | 0 | !Arg.starts_with("-fdiagnostics-color")) |
54 | 0 | 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 | 0 | else if (!AdjustedArgs.empty() && AdjustedArgs.back() == "-Xclang") |
59 | 0 | AdjustedArgs.pop_back(); |
60 | |
|
61 | 0 | if (Arg == "-fsyntax-only") |
62 | 0 | HasSyntaxOnly = true; |
63 | 0 | } |
64 | 0 | if (!HasSyntaxOnly) |
65 | 0 | AdjustedArgs = |
66 | 0 | getInsertArgumentAdjuster("-fsyntax-only")(AdjustedArgs, ""); |
67 | 0 | return AdjustedArgs; |
68 | 0 | }; |
69 | 0 | } |
70 | | |
71 | 0 | ArgumentsAdjuster getClangStripOutputAdjuster() { |
72 | 0 | return [](const CommandLineArguments &Args, StringRef /*unused*/) { |
73 | 0 | CommandLineArguments AdjustedArgs; |
74 | 0 | for (size_t i = 0, e = Args.size(); i < e; ++i) { |
75 | 0 | StringRef Arg = Args[i]; |
76 | 0 | if (!Arg.starts_with("-o")) |
77 | 0 | AdjustedArgs.push_back(Args[i]); |
78 | |
|
79 | 0 | if (Arg == "-o") { |
80 | | // Output is specified as -o foo. Skip the next argument too. |
81 | 0 | ++i; |
82 | 0 | } |
83 | | // Else, the output is specified as -ofoo. Just do nothing. |
84 | 0 | } |
85 | 0 | return AdjustedArgs; |
86 | 0 | }; |
87 | 0 | } |
88 | | |
89 | 0 | ArgumentsAdjuster getClangStripDependencyFileAdjuster() { |
90 | 0 | return [](const CommandLineArguments &Args, StringRef /*unused*/) { |
91 | 0 | auto UsingClDriver = (getDriverMode(Args) == "cl"); |
92 | |
|
93 | 0 | CommandLineArguments AdjustedArgs; |
94 | 0 | for (size_t i = 0, e = Args.size(); i < e; ++i) { |
95 | 0 | StringRef Arg = Args[i]; |
96 | | |
97 | | // These flags take an argument: -MX foo. Skip the next argument also. |
98 | 0 | if (!UsingClDriver && (Arg == "-MF" || Arg == "-MT" || Arg == "-MQ")) { |
99 | 0 | ++i; |
100 | 0 | continue; |
101 | 0 | } |
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 | 0 | if (!UsingClDriver && Arg.starts_with("-M")) |
106 | 0 | continue; |
107 | | // Under MSVC's cl driver mode, dependency file generation is controlled |
108 | | // using /showIncludes |
109 | 0 | if (Arg.starts_with("/showIncludes") || Arg.starts_with("-showIncludes")) |
110 | 0 | continue; |
111 | | |
112 | 0 | AdjustedArgs.push_back(Args[i]); |
113 | 0 | } |
114 | 0 | return AdjustedArgs; |
115 | 0 | }; |
116 | 0 | } |
117 | | |
118 | | ArgumentsAdjuster getInsertArgumentAdjuster(const CommandLineArguments &Extra, |
119 | 0 | ArgumentInsertPosition Pos) { |
120 | 0 | return [Extra, Pos](const CommandLineArguments &Args, StringRef /*unused*/) { |
121 | 0 | CommandLineArguments Return(Args); |
122 | |
|
123 | 0 | CommandLineArguments::iterator I; |
124 | 0 | if (Pos == ArgumentInsertPosition::END) { |
125 | 0 | I = llvm::find(Return, "--"); |
126 | 0 | } else { |
127 | 0 | I = Return.begin(); |
128 | 0 | ++I; // To leave the program name in place |
129 | 0 | } |
130 | |
|
131 | 0 | Return.insert(I, Extra.begin(), Extra.end()); |
132 | 0 | return Return; |
133 | 0 | }; |
134 | 0 | } |
135 | | |
136 | | ArgumentsAdjuster getInsertArgumentAdjuster(const char *Extra, |
137 | 0 | ArgumentInsertPosition Pos) { |
138 | 0 | return getInsertArgumentAdjuster(CommandLineArguments(1, Extra), Pos); |
139 | 0 | } |
140 | | |
141 | | ArgumentsAdjuster combineAdjusters(ArgumentsAdjuster First, |
142 | 0 | ArgumentsAdjuster Second) { |
143 | 0 | if (!First) |
144 | 0 | return Second; |
145 | 0 | if (!Second) |
146 | 0 | return First; |
147 | 0 | return [First, Second](const CommandLineArguments &Args, StringRef File) { |
148 | 0 | return Second(First(Args, File), File); |
149 | 0 | }; |
150 | 0 | } |
151 | | |
152 | 0 | ArgumentsAdjuster getStripPluginsAdjuster() { |
153 | 0 | return [](const CommandLineArguments &Args, StringRef /*unused*/) { |
154 | 0 | CommandLineArguments AdjustedArgs; |
155 | 0 | 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 | 0 | if (I + 4 < E && Args[I] == "-Xclang" && |
161 | 0 | (Args[I + 1] == "-load" || Args[I + 1] == "-plugin" || |
162 | 0 | llvm::StringRef(Args[I + 1]).starts_with("-plugin-arg-") || |
163 | 0 | Args[I + 1] == "-add-plugin") && |
164 | 0 | Args[I + 2] == "-Xclang") { |
165 | 0 | I += 3; |
166 | 0 | continue; |
167 | 0 | } |
168 | 0 | AdjustedArgs.push_back(Args[I]); |
169 | 0 | } |
170 | 0 | return AdjustedArgs; |
171 | 0 | }; |
172 | 0 | } |
173 | | |
174 | | } // end namespace tooling |
175 | | } // end namespace clang |