Skip to content

Commit cdea18b

Browse files
committed
[clang] Migrate clang-rename to OptTable parsing
Using OptTable to parse will allow including this tool in llvm-driver. Because CommonOptionsParser is widely used and makes use of `cl::opt` flags, it needs to be refactored to handle both. The existing `CommonOptionsParser::create()` method should continue to work for downstream users. An additional overload allows a general function to be passed in, which can do arg parsing however it likes, as long as it returns the fields that CommonOptionsParser needs. Many other simple `clang-*` tools can be similarly migrated after this.
1 parent f40f4fc commit cdea18b

File tree

7 files changed

+304
-104
lines changed

7 files changed

+304
-104
lines changed

clang/include/clang/Tooling/CommonOptionsParser.h

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,24 @@ class CommonOptionsParser {
8686
llvm::cl::NumOccurrencesFlag OccurrencesFlag = llvm::cl::OneOrMore,
8787
const char *Overview = nullptr);
8888

89+
struct Args {
90+
std::string BuildPath;
91+
std::vector<std::string> SourcePaths;
92+
std::vector<std::string> ArgsAfter;
93+
std::vector<std::string> ArgsBefore;
94+
};
95+
96+
using ArgParserCallback =
97+
std::function<llvm::Expected<Args>(int &argc, const char **argv)>;
98+
99+
/// A factory method that is similar to the above factory method, except
100+
/// this does not force use of cl::opt argument parsing. The function passed
101+
/// in is expected to handle argument parsing, and must return values needed
102+
/// by CommonOptionsParser.
103+
static llvm::Expected<CommonOptionsParser>
104+
create(int &argc, const char **argv, ArgParserCallback ArgsCallback,
105+
llvm::cl::NumOccurrencesFlag OccurrencesFlag = llvm::cl::OneOrMore);
106+
89107
/// Returns a reference to the loaded compilations database.
90108
CompilationDatabase &getCompilations() {
91109
return *Compilations;
@@ -105,10 +123,9 @@ class CommonOptionsParser {
105123
private:
106124
CommonOptionsParser() = default;
107125

108-
llvm::Error init(int &argc, const char **argv,
109-
llvm::cl::OptionCategory &Category,
110-
llvm::cl::NumOccurrencesFlag OccurrencesFlag,
111-
const char *Overview);
126+
llvm::Error
127+
init(int &argc, const char **argv, ArgParserCallback ArgsCallback,
128+
llvm::cl::NumOccurrencesFlag OccurrencesFlag = llvm::cl::OneOrMore);
112129

113130
std::unique_ptr<CompilationDatabase> Compilations;
114131
std::vector<std::string> SourcePathList;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
include "llvm/Option/OptParser.td"
2+
3+
multiclass Eq<string name, string help> {
4+
def NAME#_EQ : Joined<["--", "-"], name#"=">, HelpText<help>;
5+
def : Separate<["--", "-"], name>, Alias<!cast<Joined>(NAME#_EQ)>;
6+
}
7+
8+
defm build_path : Eq<"p", "Build path.">;
9+
defm extra_arg
10+
: Eq<"extra-arg",
11+
"Additional argument to append to the compiler command line.">;
12+
defm extra_arg_before
13+
: Eq<"extra-arg-before",
14+
"Additional argument to prepend to the compiler command line.">;

clang/lib/Tooling/CommonOptionsParser.cpp

Lines changed: 75 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,12 @@ void ArgumentsAdjustingCompilations::appendArgumentsAdjuster(
5757
Adjusters.push_back(std::move(Adjuster));
5858
}
5959

60-
std::vector<CompileCommand> ArgumentsAdjustingCompilations::getCompileCommands(
61-
StringRef FilePath) const {
60+
std::vector<CompileCommand>
61+
ArgumentsAdjustingCompilations::getCompileCommands(StringRef FilePath) const {
6262
return adjustCommands(Compilations->getCompileCommands(FilePath));
6363
}
6464

65-
std::vector<std::string>
66-
ArgumentsAdjustingCompilations::getAllFiles() const {
65+
std::vector<std::string> ArgumentsAdjustingCompilations::getAllFiles() const {
6766
return Compilations->getAllFiles();
6867
}
6968

@@ -80,58 +79,32 @@ std::vector<CompileCommand> ArgumentsAdjustingCompilations::adjustCommands(
8079
return Commands;
8180
}
8281

83-
llvm::Error CommonOptionsParser::init(
84-
int &argc, const char **argv, cl::OptionCategory &Category,
85-
llvm::cl::NumOccurrencesFlag OccurrencesFlag, const char *Overview) {
86-
87-
static cl::opt<std::string> BuildPath("p", cl::desc("Build path"),
88-
cl::Optional, cl::cat(Category),
89-
cl::sub(cl::SubCommand::getAll()));
90-
91-
static cl::list<std::string> SourcePaths(
92-
cl::Positional, cl::desc("<source0> [... <sourceN>]"), OccurrencesFlag,
93-
cl::cat(Category), cl::sub(cl::SubCommand::getAll()));
94-
95-
static cl::list<std::string> ArgsAfter(
96-
"extra-arg",
97-
cl::desc("Additional argument to append to the compiler command line"),
98-
cl::cat(Category), cl::sub(cl::SubCommand::getAll()));
99-
100-
static cl::list<std::string> ArgsBefore(
101-
"extra-arg-before",
102-
cl::desc("Additional argument to prepend to the compiler command line"),
103-
cl::cat(Category), cl::sub(cl::SubCommand::getAll()));
104-
105-
cl::ResetAllOptionOccurrences();
106-
107-
cl::HideUnrelatedOptions(Category);
108-
82+
llvm::Error
83+
CommonOptionsParser::init(int &argc, const char **argv,
84+
ArgParserCallback ArgsCallback,
85+
llvm::cl::NumOccurrencesFlag OccurrencesFlag) {
10986
std::string ErrorMessage;
11087
Compilations =
11188
FixedCompilationDatabase::loadFromCommandLine(argc, argv, ErrorMessage);
11289
if (!ErrorMessage.empty())
11390
ErrorMessage.append("\n");
114-
llvm::raw_string_ostream OS(ErrorMessage);
115-
// Stop initializing if command-line option parsing failed.
116-
if (!cl::ParseCommandLineOptions(argc, argv, Overview, &OS)) {
117-
OS.flush();
118-
return llvm::make_error<llvm::StringError>(ErrorMessage,
119-
llvm::inconvertibleErrorCode());
120-
}
12191

122-
cl::PrintOptionValues();
92+
// Stop initializing if command-line option parsing failed.
93+
auto Args = ArgsCallback(argc, argv);
94+
if (!Args)
95+
return Args.takeError();
12396

124-
SourcePathList = SourcePaths;
97+
SourcePathList = Args->SourcePaths;
12598
if ((OccurrencesFlag == cl::ZeroOrMore || OccurrencesFlag == cl::Optional) &&
12699
SourcePathList.empty())
127100
return llvm::Error::success();
128101
if (!Compilations) {
129-
if (!BuildPath.empty()) {
130-
Compilations =
131-
CompilationDatabase::autoDetectFromDirectory(BuildPath, ErrorMessage);
102+
if (!Args->BuildPath.empty()) {
103+
Compilations = CompilationDatabase::autoDetectFromDirectory(
104+
Args->BuildPath, ErrorMessage);
132105
} else {
133-
Compilations = CompilationDatabase::autoDetectFromSource(SourcePaths[0],
134-
ErrorMessage);
106+
Compilations = CompilationDatabase::autoDetectFromSource(
107+
Args->SourcePaths[0], ErrorMessage);
135108
}
136109
if (!Compilations) {
137110
llvm::errs() << "Error while trying to load a compilation database:\n"
@@ -141,24 +114,72 @@ llvm::Error CommonOptionsParser::init(
141114
}
142115
}
143116
auto AdjustingCompilations =
144-
std::make_unique<ArgumentsAdjustingCompilations>(
145-
std::move(Compilations));
146-
Adjuster =
147-
getInsertArgumentAdjuster(ArgsBefore, ArgumentInsertPosition::BEGIN);
117+
std::make_unique<ArgumentsAdjustingCompilations>(std::move(Compilations));
118+
Adjuster = getInsertArgumentAdjuster(Args->ArgsBefore,
119+
ArgumentInsertPosition::BEGIN);
148120
Adjuster = combineAdjusters(
149121
std::move(Adjuster),
150-
getInsertArgumentAdjuster(ArgsAfter, ArgumentInsertPosition::END));
122+
getInsertArgumentAdjuster(Args->ArgsAfter, ArgumentInsertPosition::END));
151123
AdjustingCompilations->appendArgumentsAdjuster(Adjuster);
152124
Compilations = std::move(AdjustingCompilations);
153125
return llvm::Error::success();
154126
}
155127

128+
CommonOptionsParser::ArgParserCallback
129+
makeClOptParserCallback(llvm::cl::OptionCategory &Category,
130+
llvm::cl::NumOccurrencesFlag OccurrencesFlag,
131+
const char *Overview) {
132+
return [&Category, OccurrencesFlag, Overview](
133+
int &argc,
134+
const char **argv) -> llvm::Expected<CommonOptionsParser::Args> {
135+
static cl::opt<std::string> BuildPath("p", cl::desc("Build path"),
136+
cl::Optional, cl::cat(Category),
137+
cl::sub(cl::SubCommand::getAll()));
138+
139+
static cl::list<std::string> SourcePaths(
140+
cl::Positional, cl::desc("<source0> [... <sourceN>]"), OccurrencesFlag,
141+
cl::cat(Category), cl::sub(cl::SubCommand::getAll()));
142+
143+
static cl::list<std::string> ArgsAfter(
144+
"extra-arg",
145+
cl::desc("Additional argument to append to the compiler command line"),
146+
cl::cat(Category), cl::sub(cl::SubCommand::getAll()));
147+
148+
static cl::list<std::string> ArgsBefore(
149+
"extra-arg-before",
150+
cl::desc("Additional argument to prepend to the compiler command line"),
151+
cl::cat(Category), cl::sub(cl::SubCommand::getAll()));
152+
153+
cl::ResetAllOptionOccurrences();
154+
155+
cl::HideUnrelatedOptions(Category);
156+
157+
std::string ErrorMessage;
158+
llvm::raw_string_ostream OS(ErrorMessage);
159+
if (!cl::ParseCommandLineOptions(argc, argv, Overview, &OS)) {
160+
OS.flush();
161+
return llvm::make_error<llvm::StringError>(
162+
ErrorMessage, llvm::inconvertibleErrorCode());
163+
}
164+
return CommonOptionsParser::Args{BuildPath, SourcePaths, ArgsAfter,
165+
ArgsBefore};
166+
};
167+
}
168+
156169
llvm::Expected<CommonOptionsParser> CommonOptionsParser::create(
157170
int &argc, const char **argv, llvm::cl::OptionCategory &Category,
158171
llvm::cl::NumOccurrencesFlag OccurrencesFlag, const char *Overview) {
172+
return create(argc, argv,
173+
makeClOptParserCallback(Category, OccurrencesFlag, Overview),
174+
OccurrencesFlag);
175+
}
176+
177+
llvm::Expected<CommonOptionsParser>
178+
CommonOptionsParser::create(int &argc, const char **argv,
179+
ArgParserCallback ArgsCallback,
180+
llvm::cl::NumOccurrencesFlag OccurrencesFlag) {
159181
CommonOptionsParser Parser;
160-
llvm::Error Err =
161-
Parser.init(argc, argv, Category, OccurrencesFlag, Overview);
182+
llvm::Error Err = Parser.init(argc, argv, ArgsCallback, OccurrencesFlag);
162183
if (Err)
163184
return std::move(Err);
164185
return std::move(Parser);
@@ -167,7 +188,9 @@ llvm::Expected<CommonOptionsParser> CommonOptionsParser::create(
167188
CommonOptionsParser::CommonOptionsParser(
168189
int &argc, const char **argv, cl::OptionCategory &Category,
169190
llvm::cl::NumOccurrencesFlag OccurrencesFlag, const char *Overview) {
170-
llvm::Error Err = init(argc, argv, Category, OccurrencesFlag, Overview);
191+
llvm::Error Err = init(
192+
argc, argv, makeClOptParserCallback(Category, OccurrencesFlag, Overview),
193+
OccurrencesFlag);
171194
if (Err) {
172195
llvm::report_fatal_error(
173196
Twine("CommonOptionsParser: failed to parse command-line arguments. ") +

clang/tools/clang-rename/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,15 @@ set(LLVM_LINK_COMPONENTS
33
Support
44
)
55

6+
set(LLVM_TARGET_DEFINITIONS Opts.td)
7+
tablegen(LLVM Opts.inc -gen-opt-parser-defs)
8+
add_public_tablegen_target(ClangRenameOptsTableGen)
9+
610
add_clang_tool(clang-rename
711
ClangRename.cpp
12+
13+
DEPENDS
14+
ClangRenameOptsTableGen
815
)
916

1017
clang_target_link_libraries(clang-rename

0 commit comments

Comments
 (0)