Skip to content

Commit 06b2847

Browse files
Merge pull request #8522 from apple/dl/swift/release/6.0/clang-Move-CCC_OVERRIDE_OPTIONS-implementation-to-Driver-85425
[clang] Move CCC_OVERRIDE_OPTIONS implementation to Driver
2 parents d0f5f18 + db693a3 commit 06b2847

File tree

3 files changed

+144
-135
lines changed

3 files changed

+144
-135
lines changed

clang/include/clang/Driver/Driver.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@
2828
#include "llvm/Option/ArgList.h"
2929
#include "llvm/Support/StringSaver.h"
3030

31-
#include <list>
3231
#include <map>
32+
#include <set>
3333
#include <string>
3434
#include <vector>
3535

@@ -829,6 +829,13 @@ llvm::Error expandResponseFiles(SmallVectorImpl<const char *> &Args,
829829
/// Checks whether the value produced by getDriverMode is for 'cache' mode.
830830
bool isClangCache(StringRef DriverMode);
831831

832+
/// Apply a space separated list of edits to the input argument lists.
833+
/// See applyOneOverrideOption.
834+
void applyOverrideOptions(SmallVectorImpl<const char *> &Args,
835+
const char *OverrideOpts,
836+
llvm::StringSet<> &SavedStrings,
837+
raw_ostream *OS = nullptr);
838+
832839
} // end namespace driver
833840
} // end namespace clang
834841

clang/lib/Driver/Driver.cpp

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
#include "llvm/Support/PrettyStackTrace.h"
9292
#include "llvm/Support/Process.h"
9393
#include "llvm/Support/Program.h"
94+
#include "llvm/Support/Regex.h"
9495
#include "llvm/Support/StringSaver.h"
9596
#include "llvm/Support/VirtualFileSystem.h"
9697
#include "llvm/Support/raw_ostream.h"
@@ -6673,3 +6674,131 @@ llvm::Error driver::expandResponseFiles(SmallVectorImpl<const char *> &Args,
66736674
bool driver::isClangCache(StringRef DriverMode) {
66746675
return DriverMode == "cache";
66756676
}
6677+
6678+
static const char *GetStableCStr(llvm::StringSet<> &SavedStrings, StringRef S) {
6679+
return SavedStrings.insert(S).first->getKeyData();
6680+
}
6681+
6682+
/// Apply a list of edits to the input argument lists.
6683+
///
6684+
/// The input string is a space separated list of edits to perform,
6685+
/// they are applied in order to the input argument lists. Edits
6686+
/// should be one of the following forms:
6687+
///
6688+
/// '#': Silence information about the changes to the command line arguments.
6689+
///
6690+
/// '^': Add FOO as a new argument at the beginning of the command line.
6691+
///
6692+
/// '+': Add FOO as a new argument at the end of the command line.
6693+
///
6694+
/// 's/XXX/YYY/': Substitute the regular expression XXX with YYY in the command
6695+
/// line.
6696+
///
6697+
/// 'xOPTION': Removes all instances of the literal argument OPTION.
6698+
///
6699+
/// 'XOPTION': Removes all instances of the literal argument OPTION,
6700+
/// and the following argument.
6701+
///
6702+
/// 'Ox': Removes all flags matching 'O' or 'O[sz0-9]' and adds 'Ox'
6703+
/// at the end of the command line.
6704+
///
6705+
/// \param OS - The stream to write edit information to.
6706+
/// \param Args - The vector of command line arguments.
6707+
/// \param Edit - The override command to perform.
6708+
/// \param SavedStrings - Set to use for storing string representations.
6709+
static void applyOneOverrideOption(raw_ostream &OS,
6710+
SmallVectorImpl<const char *> &Args,
6711+
StringRef Edit,
6712+
llvm::StringSet<> &SavedStrings) {
6713+
// This does not need to be efficient.
6714+
6715+
if (Edit[0] == '^') {
6716+
const char *Str = GetStableCStr(SavedStrings, Edit.substr(1));
6717+
OS << "### Adding argument " << Str << " at beginning\n";
6718+
Args.insert(Args.begin() + 1, Str);
6719+
} else if (Edit[0] == '+') {
6720+
const char *Str = GetStableCStr(SavedStrings, Edit.substr(1));
6721+
OS << "### Adding argument " << Str << " at end\n";
6722+
Args.push_back(Str);
6723+
} else if (Edit[0] == 's' && Edit[1] == '/' && Edit.ends_with("/") &&
6724+
Edit.slice(2, Edit.size() - 1).contains('/')) {
6725+
StringRef MatchPattern = Edit.substr(2).split('/').first;
6726+
StringRef ReplPattern = Edit.substr(2).split('/').second;
6727+
ReplPattern = ReplPattern.slice(0, ReplPattern.size() - 1);
6728+
6729+
for (unsigned i = 1, e = Args.size(); i != e; ++i) {
6730+
// Ignore end-of-line response file markers
6731+
if (Args[i] == nullptr)
6732+
continue;
6733+
std::string Repl = llvm::Regex(MatchPattern).sub(ReplPattern, Args[i]);
6734+
6735+
if (Repl != Args[i]) {
6736+
OS << "### Replacing '" << Args[i] << "' with '" << Repl << "'\n";
6737+
Args[i] = GetStableCStr(SavedStrings, Repl);
6738+
}
6739+
}
6740+
} else if (Edit[0] == 'x' || Edit[0] == 'X') {
6741+
auto Option = Edit.substr(1);
6742+
for (unsigned i = 1; i < Args.size();) {
6743+
if (Option == Args[i]) {
6744+
OS << "### Deleting argument " << Args[i] << '\n';
6745+
Args.erase(Args.begin() + i);
6746+
if (Edit[0] == 'X') {
6747+
if (i < Args.size()) {
6748+
OS << "### Deleting argument " << Args[i] << '\n';
6749+
Args.erase(Args.begin() + i);
6750+
} else
6751+
OS << "### Invalid X edit, end of command line!\n";
6752+
}
6753+
} else
6754+
++i;
6755+
}
6756+
} else if (Edit[0] == 'O') {
6757+
for (unsigned i = 1; i < Args.size();) {
6758+
const char *A = Args[i];
6759+
// Ignore end-of-line response file markers
6760+
if (A == nullptr)
6761+
continue;
6762+
if (A[0] == '-' && A[1] == 'O' &&
6763+
(A[2] == '\0' || (A[3] == '\0' && (A[2] == 's' || A[2] == 'z' ||
6764+
('0' <= A[2] && A[2] <= '9'))))) {
6765+
OS << "### Deleting argument " << Args[i] << '\n';
6766+
Args.erase(Args.begin() + i);
6767+
} else
6768+
++i;
6769+
}
6770+
OS << "### Adding argument " << Edit << " at end\n";
6771+
Args.push_back(GetStableCStr(SavedStrings, '-' + Edit.str()));
6772+
} else {
6773+
OS << "### Unrecognized edit: " << Edit << "\n";
6774+
}
6775+
}
6776+
6777+
void driver::applyOverrideOptions(SmallVectorImpl<const char *> &Args,
6778+
const char *OverrideStr,
6779+
llvm::StringSet<> &SavedStrings,
6780+
raw_ostream *OS) {
6781+
if (!OS)
6782+
OS = &llvm::nulls();
6783+
6784+
if (OverrideStr[0] == '#') {
6785+
++OverrideStr;
6786+
OS = &llvm::nulls();
6787+
}
6788+
6789+
*OS << "### CCC_OVERRIDE_OPTIONS: " << OverrideStr << "\n";
6790+
6791+
// This does not need to be efficient.
6792+
6793+
const char *S = OverrideStr;
6794+
while (*S) {
6795+
const char *End = ::strchr(S, ' ');
6796+
if (!End)
6797+
End = S + strlen(S);
6798+
if (End != S)
6799+
applyOneOverrideOption(*OS, Args, std::string(S, End), SavedStrings);
6800+
S = End;
6801+
if (*S != '\0')
6802+
++S;
6803+
}
6804+
}

clang/tools/driver/driver.cpp

Lines changed: 7 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "llvm/ADT/ArrayRef.h"
3131
#include "llvm/ADT/SmallString.h"
3232
#include "llvm/ADT/SmallVector.h"
33+
#include "llvm/ADT/StringSet.h"
3334
#include "llvm/Option/ArgList.h"
3435
#include "llvm/Option/OptTable.h"
3536
#include "llvm/Option/Option.h"
@@ -45,7 +46,6 @@
4546
#include "llvm/Support/PrettyStackTrace.h"
4647
#include "llvm/Support/Process.h"
4748
#include "llvm/Support/Program.h"
48-
#include "llvm/Support/Regex.h"
4949
#include "llvm/Support/Signals.h"
5050
#include "llvm/Support/StringSaver.h"
5151
#include "llvm/Support/TargetSelect.h"
@@ -82,136 +82,8 @@ std::string GetExecutablePath(const char *Argv0, bool CanonicalPrefixes) {
8282
return llvm::sys::fs::getMainExecutable(Argv0, P);
8383
}
8484

85-
static const char *GetStableCStr(std::set<std::string> &SavedStrings,
86-
StringRef S) {
87-
return SavedStrings.insert(std::string(S)).first->c_str();
88-
}
89-
90-
/// ApplyQAOverride - Apply a list of edits to the input argument lists.
91-
///
92-
/// The input string is a space separate list of edits to perform,
93-
/// they are applied in order to the input argument lists. Edits
94-
/// should be one of the following forms:
95-
///
96-
/// '#': Silence information about the changes to the command line arguments.
97-
///
98-
/// '^': Add FOO as a new argument at the beginning of the command line.
99-
///
100-
/// '+': Add FOO as a new argument at the end of the command line.
101-
///
102-
/// 's/XXX/YYY/': Substitute the regular expression XXX with YYY in the command
103-
/// line.
104-
///
105-
/// 'xOPTION': Removes all instances of the literal argument OPTION.
106-
///
107-
/// 'XOPTION': Removes all instances of the literal argument OPTION,
108-
/// and the following argument.
109-
///
110-
/// 'Ox': Removes all flags matching 'O' or 'O[sz0-9]' and adds 'Ox'
111-
/// at the end of the command line.
112-
///
113-
/// \param OS - The stream to write edit information to.
114-
/// \param Args - The vector of command line arguments.
115-
/// \param Edit - The override command to perform.
116-
/// \param SavedStrings - Set to use for storing string representations.
117-
static void ApplyOneQAOverride(raw_ostream &OS,
118-
SmallVectorImpl<const char*> &Args,
119-
StringRef Edit,
120-
std::set<std::string> &SavedStrings) {
121-
// This does not need to be efficient.
122-
123-
if (Edit[0] == '^') {
124-
const char *Str =
125-
GetStableCStr(SavedStrings, Edit.substr(1));
126-
OS << "### Adding argument " << Str << " at beginning\n";
127-
Args.insert(Args.begin() + 1, Str);
128-
} else if (Edit[0] == '+') {
129-
const char *Str =
130-
GetStableCStr(SavedStrings, Edit.substr(1));
131-
OS << "### Adding argument " << Str << " at end\n";
132-
Args.push_back(Str);
133-
} else if (Edit[0] == 's' && Edit[1] == '/' && Edit.endswith("/") &&
134-
Edit.slice(2, Edit.size() - 1).contains('/')) {
135-
StringRef MatchPattern = Edit.substr(2).split('/').first;
136-
StringRef ReplPattern = Edit.substr(2).split('/').second;
137-
ReplPattern = ReplPattern.slice(0, ReplPattern.size()-1);
138-
139-
for (unsigned i = 1, e = Args.size(); i != e; ++i) {
140-
// Ignore end-of-line response file markers
141-
if (Args[i] == nullptr)
142-
continue;
143-
std::string Repl = llvm::Regex(MatchPattern).sub(ReplPattern, Args[i]);
144-
145-
if (Repl != Args[i]) {
146-
OS << "### Replacing '" << Args[i] << "' with '" << Repl << "'\n";
147-
Args[i] = GetStableCStr(SavedStrings, Repl);
148-
}
149-
}
150-
} else if (Edit[0] == 'x' || Edit[0] == 'X') {
151-
auto Option = Edit.substr(1);
152-
for (unsigned i = 1; i < Args.size();) {
153-
if (Option == Args[i]) {
154-
OS << "### Deleting argument " << Args[i] << '\n';
155-
Args.erase(Args.begin() + i);
156-
if (Edit[0] == 'X') {
157-
if (i < Args.size()) {
158-
OS << "### Deleting argument " << Args[i] << '\n';
159-
Args.erase(Args.begin() + i);
160-
} else
161-
OS << "### Invalid X edit, end of command line!\n";
162-
}
163-
} else
164-
++i;
165-
}
166-
} else if (Edit[0] == 'O') {
167-
for (unsigned i = 1; i < Args.size();) {
168-
const char *A = Args[i];
169-
// Ignore end-of-line response file markers
170-
if (A == nullptr)
171-
continue;
172-
if (A[0] == '-' && A[1] == 'O' &&
173-
(A[2] == '\0' ||
174-
(A[3] == '\0' && (A[2] == 's' || A[2] == 'z' ||
175-
('0' <= A[2] && A[2] <= '9'))))) {
176-
OS << "### Deleting argument " << Args[i] << '\n';
177-
Args.erase(Args.begin() + i);
178-
} else
179-
++i;
180-
}
181-
OS << "### Adding argument " << Edit << " at end\n";
182-
Args.push_back(GetStableCStr(SavedStrings, '-' + Edit.str()));
183-
} else {
184-
OS << "### Unrecognized edit: " << Edit << "\n";
185-
}
186-
}
187-
188-
/// ApplyQAOverride - Apply a comma separate list of edits to the
189-
/// input argument lists. See ApplyOneQAOverride.
190-
static void ApplyQAOverride(SmallVectorImpl<const char*> &Args,
191-
const char *OverrideStr,
192-
std::set<std::string> &SavedStrings) {
193-
raw_ostream *OS = &llvm::errs();
194-
195-
if (OverrideStr[0] == '#') {
196-
++OverrideStr;
197-
OS = &llvm::nulls();
198-
}
199-
200-
*OS << "### CCC_OVERRIDE_OPTIONS: " << OverrideStr << "\n";
201-
202-
// This does not need to be efficient.
203-
204-
const char *S = OverrideStr;
205-
while (*S) {
206-
const char *End = ::strchr(S, ' ');
207-
if (!End)
208-
End = S + strlen(S);
209-
if (End != S)
210-
ApplyOneQAOverride(*OS, Args, std::string(S, End), SavedStrings);
211-
S = End;
212-
if (*S != '\0')
213-
++S;
214-
}
85+
static const char *GetStableCStr(llvm::StringSet<> &SavedStrings, StringRef S) {
86+
return SavedStrings.insert(S).first->getKeyData();
21587
}
21688

21789
extern int cc1_main(ArrayRef<const char *> Argv, const char *Argv0,
@@ -230,7 +102,7 @@ extern int cc1gen_reproducer_main(ArrayRef<const char *> Argv,
230102

231103
static void insertTargetAndModeArgs(const ParsedClangName &NameParts,
232104
SmallVectorImpl<const char *> &ArgVector,
233-
std::set<std::string> &SavedStrings) {
105+
llvm::StringSet<> &SavedStrings) {
234106
// Put target and mode arguments at the start of argument list so that
235107
// arguments specified in command line could override them. Avoid putting
236108
// them at index 0, as an option like '-cc1' must remain the first.
@@ -482,12 +354,13 @@ int clang_main(int Argc, char **Argv, const llvm::ToolContext &ToolContext) {
482354
}
483355
}
484356

485-
std::set<std::string> SavedStrings;
357+
llvm::StringSet<> SavedStrings;
486358
// Handle CCC_OVERRIDE_OPTIONS, used for editing a command line behind the
487359
// scenes.
488360
if (const char *OverrideStr = ::getenv("CCC_OVERRIDE_OPTIONS")) {
489361
// FIXME: Driver shouldn't take extra initial argument.
490-
ApplyQAOverride(Args, OverrideStr, SavedStrings);
362+
driver::applyOverrideOptions(Args, OverrideStr, SavedStrings,
363+
&llvm::errs());
491364
}
492365

493366
std::string Path = GetExecutablePath(ToolContext.Path, CanonicalPrefixes);

0 commit comments

Comments
 (0)