Skip to content

Commit 70410a2

Browse files
committed
[clang][cli] Let denormalizer decide how to render the option based on the option class
Before this patch, you needed to use `AutoNormalizeEnumJoined` whenever you wanted to **de**normalize joined enum. Besides the naming confusion, this means the fact the option is joined is specified in two places: in the normalization multiclass and in the `Joined<["-"], ...>` multiclass. This patch makes this work automatically, taking into account the `OptionClass` of options. Also, the enum denormalizer now just looks up the spelling of the present enum case in a table and forwards it to the string denormalizer. I also added more tests that exercise this. Reviewed By: dexonsmith Original patch by Daniel Grumberg. Differential Revision: https://reviews.llvm.org/D84189
1 parent 27b7d64 commit 70410a2

File tree

4 files changed

+82
-45
lines changed

4 files changed

+82
-45
lines changed

clang/include/clang/Driver/Options.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4882,7 +4882,7 @@ def arcmt_action_EQ : Joined<["-"], "arcmt-action=">, Flags<[CC1Option, NoDriver
48824882
NormalizedValuesScope<"FrontendOptions">,
48834883
NormalizedValues<["ARCMT_Check", "ARCMT_Modify", "ARCMT_Migrate"]>,
48844884
MarshallingInfoString<"FrontendOpts.ARCMTAction", "ARCMT_None">,
4885-
AutoNormalizeEnumJoined;
4885+
AutoNormalizeEnum;
48864886

48874887
def opt_record_file : Separate<["-"], "opt-record-file">,
48884888
HelpText<"File name to use for YAML optimization record output">,

clang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 39 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,8 @@ static Optional<bool> normalizeSimpleNegativeFlag(OptSpecifier Opt, unsigned,
152152
/// argument.
153153
static void denormalizeSimpleFlag(SmallVectorImpl<const char *> &Args,
154154
const char *Spelling,
155-
CompilerInvocation::StringAllocator, unsigned,
156-
/*T*/...) {
155+
CompilerInvocation::StringAllocator,
156+
Option::OptionClass, unsigned, /*T*/...) {
157157
Args.push_back(Spelling);
158158
}
159159

@@ -200,12 +200,41 @@ static auto makeBooleanOptionNormalizer(bool Value, bool OtherValue,
200200

201201
static auto makeBooleanOptionDenormalizer(bool Value) {
202202
return [Value](SmallVectorImpl<const char *> &Args, const char *Spelling,
203-
CompilerInvocation::StringAllocator, unsigned, bool KeyPath) {
203+
CompilerInvocation::StringAllocator, Option::OptionClass,
204+
unsigned, bool KeyPath) {
204205
if (KeyPath == Value)
205206
Args.push_back(Spelling);
206207
};
207208
}
208209

210+
static void denormalizeStringImpl(SmallVectorImpl<const char *> &Args,
211+
const char *Spelling,
212+
CompilerInvocation::StringAllocator SA,
213+
Option::OptionClass OptClass, unsigned,
214+
Twine Value) {
215+
switch (OptClass) {
216+
case Option::SeparateClass:
217+
case Option::JoinedOrSeparateClass:
218+
Args.push_back(Spelling);
219+
Args.push_back(SA(Value));
220+
break;
221+
case Option::JoinedClass:
222+
Args.push_back(SA(Twine(Spelling) + Value));
223+
break;
224+
default:
225+
llvm_unreachable("Cannot denormalize an option with option class "
226+
"incompatible with string denormalization.");
227+
}
228+
}
229+
230+
template <typename T>
231+
static void
232+
denormalizeString(SmallVectorImpl<const char *> &Args, const char *Spelling,
233+
CompilerInvocation::StringAllocator SA,
234+
Option::OptionClass OptClass, unsigned TableIndex, T Value) {
235+
denormalizeStringImpl(Args, Spelling, SA, OptClass, TableIndex, Twine(Value));
236+
}
237+
209238
static Optional<SimpleEnumValue>
210239
findValueTableByName(const SimpleEnumValueTable &Table, StringRef Name) {
211240
for (int I = 0, E = Table.Size; I != E; ++I)
@@ -247,12 +276,13 @@ static llvm::Optional<unsigned> normalizeSimpleEnum(OptSpecifier Opt,
247276
static void denormalizeSimpleEnumImpl(SmallVectorImpl<const char *> &Args,
248277
const char *Spelling,
249278
CompilerInvocation::StringAllocator SA,
279+
Option::OptionClass OptClass,
250280
unsigned TableIndex, unsigned Value) {
251281
assert(TableIndex < SimpleEnumValueTablesSize);
252282
const SimpleEnumValueTable &Table = SimpleEnumValueTables[TableIndex];
253283
if (auto MaybeEnumVal = findValueTableByValue(Table, Value)) {
254-
Args.push_back(Spelling);
255-
Args.push_back(MaybeEnumVal->Name);
284+
denormalizeString(Args, Spelling, SA, OptClass, TableIndex,
285+
MaybeEnumVal->Name);
256286
} else {
257287
llvm_unreachable("The simple enum value was not correctly defined in "
258288
"the tablegen option description");
@@ -263,24 +293,12 @@ template <typename T>
263293
static void denormalizeSimpleEnum(SmallVectorImpl<const char *> &Args,
264294
const char *Spelling,
265295
CompilerInvocation::StringAllocator SA,
296+
Option::OptionClass OptClass,
266297
unsigned TableIndex, T Value) {
267-
return denormalizeSimpleEnumImpl(Args, Spelling, SA, TableIndex,
298+
return denormalizeSimpleEnumImpl(Args, Spelling, SA, OptClass, TableIndex,
268299
static_cast<unsigned>(Value));
269300
}
270301

271-
static void denormalizeSimpleEnumJoined(SmallVectorImpl<const char *> &Args,
272-
const char *Spelling,
273-
CompilerInvocation::StringAllocator SA,
274-
unsigned TableIndex, unsigned Value) {
275-
assert(TableIndex < SimpleEnumValueTablesSize);
276-
const SimpleEnumValueTable &Table = SimpleEnumValueTables[TableIndex];
277-
if (auto MaybeEnumVal = findValueTableByValue(Table, Value))
278-
Args.push_back(SA(Twine(Spelling) + MaybeEnumVal->Name));
279-
else
280-
llvm_unreachable("The simple enum value was not correctly defined in "
281-
"the tablegen option description");
282-
}
283-
284302
static Optional<std::string> normalizeString(OptSpecifier Opt, int TableIndex,
285303
const ArgList &Args,
286304
DiagnosticsEngine &Diags) {
@@ -290,25 +308,6 @@ static Optional<std::string> normalizeString(OptSpecifier Opt, int TableIndex,
290308
return std::string(Arg->getValue());
291309
}
292310

293-
static void denormalizeString(SmallVectorImpl<const char *> &Args,
294-
const char *Spelling,
295-
CompilerInvocation::StringAllocator SA, unsigned,
296-
Twine Value) {
297-
Args.push_back(Spelling);
298-
Args.push_back(SA(Value));
299-
}
300-
301-
template <typename T,
302-
std::enable_if_t<!std::is_convertible<T, Twine>::value &&
303-
std::is_constructible<Twine, T>::value,
304-
bool> = false>
305-
static void denormalizeString(SmallVectorImpl<const char *> &Args,
306-
const char *Spelling,
307-
CompilerInvocation::StringAllocator SA,
308-
unsigned TableIndex, T Value) {
309-
denormalizeString(Args, Spelling, SA, TableIndex, Twine(Value));
310-
}
311-
312311
template <typename IntTy>
313312
static Optional<IntTy> normalizeStringIntegral(OptSpecifier Opt, int,
314313
const ArgList &Args,
@@ -3267,7 +3266,8 @@ void CompilerInvocation::generateCC1CommandLine(
32673266
(Extracted != \
32683267
static_cast<decltype(this->KEYPATH)>( \
32693268
(IMPLIED_CHECK) ? (IMPLIED_VALUE) : (DEFAULT_VALUE)))) \
3270-
DENORMALIZER(Args, SPELLING, SA, TABLE_INDEX, Extracted); \
3269+
DENORMALIZER(Args, SPELLING, SA, Option::KIND##Class, TABLE_INDEX, \
3270+
Extracted); \
32713271
}(EXTRACTOR(this->KEYPATH)); \
32723272
}
32733273

clang/unittests/Frontend/CompilerInvocationTest.cpp

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -342,30 +342,70 @@ TEST_F(CommandLineTest, CanGenerateCC1CommandLineSeparateRequiredAbsent) {
342342
ASSERT_THAT(GeneratedArgs, Contains(StrEq(DefaultTriple.c_str())));
343343
}
344344

345-
TEST_F(CommandLineTest, CanGenerateCC1CommandLineSeparateEnumNonDefault) {
345+
TEST_F(CommandLineTest, SeparateEnumNonDefault) {
346346
const char *Args[] = {"-mrelocation-model", "static"};
347347

348348
CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
349349

350350
ASSERT_FALSE(Diags->hasErrorOccurred());
351+
ASSERT_EQ(Invocation.getCodeGenOpts().RelocationModel, Reloc::Model::Static);
351352

352353
Invocation.generateCC1CommandLine(GeneratedArgs, *this);
353354

354355
// Non default relocation model.
356+
ASSERT_THAT(GeneratedArgs, Contains(StrEq("-mrelocation-model")));
355357
ASSERT_THAT(GeneratedArgs, Contains(StrEq("static")));
358+
ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-mrelocation-model=static"))));
356359
}
357360

358-
TEST_F(CommandLineTest, CanGenerateCC1COmmandLineSeparateEnumDefault) {
361+
TEST_F(CommandLineTest, SeparateEnumDefault) {
359362
const char *Args[] = {"-mrelocation-model", "pic"};
360363

361364
CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
362365

363366
ASSERT_FALSE(Diags->hasErrorOccurred());
367+
ASSERT_EQ(Invocation.getCodeGenOpts().RelocationModel, Reloc::Model::PIC_);
364368

365369
Invocation.generateCC1CommandLine(GeneratedArgs, *this);
366370

367371
// Default relocation model.
372+
ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-mrelocation-model"))));
368373
ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("pic"))));
374+
ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-mrelocation-model=pic"))));
375+
}
376+
377+
TEST_F(CommandLineTest, JoinedEnumNonDefault) {
378+
const char *Args[] = {"-fobjc-dispatch-method=non-legacy"};
379+
380+
CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
381+
382+
ASSERT_FALSE(Diags->hasErrorOccurred());
383+
ASSERT_EQ(Invocation.getCodeGenOpts().getObjCDispatchMethod(),
384+
CodeGenOptions::NonLegacy);
385+
386+
Invocation.generateCC1CommandLine(GeneratedArgs, *this);
387+
388+
ASSERT_THAT(GeneratedArgs,
389+
Contains(StrEq("-fobjc-dispatch-method=non-legacy")));
390+
ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fobjc-dispatch-method="))));
391+
ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("non-legacy"))));
392+
}
393+
394+
TEST_F(CommandLineTest, JoinedEnumDefault) {
395+
const char *Args[] = {"-fobjc-dispatch-method=legacy"};
396+
397+
CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
398+
399+
ASSERT_FALSE(Diags->hasErrorOccurred());
400+
ASSERT_EQ(Invocation.getCodeGenOpts().getObjCDispatchMethod(),
401+
CodeGenOptions::Legacy);
402+
403+
Invocation.generateCC1CommandLine(GeneratedArgs, *this);
404+
405+
ASSERT_THAT(GeneratedArgs,
406+
Not(Contains(StrEq("-fobjc-dispatch-method=legacy"))));
407+
ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fobjc-dispatch-method="))));
408+
ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("legacy"))));
369409
}
370410

371411
// Tree of boolean options that can be (directly or transitively) implied by

llvm/include/llvm/Option/OptParser.td

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -205,9 +205,6 @@ class AutoNormalizeEnum {
205205
code Normalizer = "normalizeSimpleEnum";
206206
code Denormalizer = "denormalizeSimpleEnum";
207207
}
208-
class AutoNormalizeEnumJoined : AutoNormalizeEnum {
209-
code Denormalizer = "denormalizeSimpleEnumJoined";
210-
}
211208
class ValueMerger<code merger> { code ValueMerger = merger; }
212209
class ValueExtractor<code extractor> { code ValueExtractor = extractor; }
213210

0 commit comments

Comments
 (0)