LLVM: lib/Support/CommandLine.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
19
21
31#include "llvm/Config/config.h"
44#include
45#include
46#include
47using namespace llvm;
48using namespace cl;
49
50#define DEBUG_TYPE "commandline"
51
52
53
54
55namespace llvm {
56namespace cl {
69
75}
76}
77
78
79void GenericOptionValue::anchor() {}
82void Option::anchor() {}
96
97
98
100
104
106 size_t Len = ArgName.size();
107 if (Len == 1)
110}
111
114 for (size_t I = 0; I < Pad; ++I) {
115 Prefix.push_back(' ');
116 }
119}
120
121
124}
128}
129
130
131namespace {
132
133class PrintArg {
135 size_t Pad;
136public:
137 PrintArg(StringRef ArgName, size_t Pad = DefaultPad) : ArgName(ArgName), Pad(Pad) {}
139};
140
142 OS << argPrefix(Arg.ArgName, Arg.Pad) << Arg.ArgName;
143 return OS;
144}
145
146class CommandLineParser {
147public:
148
149
150 std::string ProgramName;
152
153
154 std::vector MoreHelp;
155
156
157
158
160
161
163
164
166
168
170
173 bool LongOptionsUseDoubleDash = false);
174
176 if (Opt.Subs.empty()) {
178 return;
179 }
181 for (auto *SC : RegisteredSubCommands)
182 Action(*SC);
184 return;
185 }
186 for (auto *SC : Opt.Subs) {
188 "SubCommand::getAll() should not be used with other subcommands");
189 Action(*SC);
190 }
191 }
192
195 return;
196 if (->OptionsMap.insert(std::make_pair(Name, &Opt)).second) {
197 errs() << ProgramName << ": CommandLine Error: Option '" << Name
198 << "' registered more than once!\n";
199 report_fatal_error("inconsistency in registered CommandLine options");
200 }
201 }
202
204 forEachSubCommand(
205 Opt, [&](SubCommand &SC) { addLiteralOption(Opt, &SC, Name); });
206 }
207
209 bool HadErrors = false;
210 if (O->hasArgStr()) {
211
212 if (O->isDefaultOption() && SC->OptionsMap.contains(O->ArgStr))
213 return;
214
215
216 if (->OptionsMap.insert(std::make_pair(O->ArgStr, O)).second) {
217 errs() << ProgramName << ": CommandLine Error: Option '" << O->ArgStr
218 << "' registered more than once!\n";
219 HadErrors = true;
220 }
221 }
222
223
225 SC->PositionalOpts.push_back(O);
226 else if (O->getMiscFlags() & cl::Sink)
227 SC->SinkOpts.push_back(O);
229 if (SC->ConsumeAfterOpt) {
230 O->error("Cannot specify more than one option with cl::ConsumeAfter!");
231 HadErrors = true;
232 }
234 }
235
236
237
238
239
240 if (HadErrors)
241 report_fatal_error("inconsistency in registered CommandLine options");
242 }
243
244 void addOption(Option *O, bool ProcessDefaultOption = false) {
245 if (!ProcessDefaultOption && O->isDefaultOption()) {
247 return;
248 }
249 forEachSubCommand(*O, [&](SubCommand &SC) { addOption(O, &SC); });
250 }
251
254 O->getExtraOptionNames(OptionNames);
255 if (O->hasArgStr())
257
260 for (auto Name : OptionNames) {
262 if (I != End && I->getValue() == O)
264 }
265
269 if (*Opt == O) {
271 break;
272 }
273 }
274 else if (O->getMiscFlags() & cl::Sink)
275 for (auto *Opt = Sub.SinkOpts.begin(); Opt != Sub.SinkOpts.end(); ++Opt) {
276 if (*Opt == O) {
278 break;
279 }
280 }
283 }
284
285 void removeOption(Option *O) {
286 forEachSubCommand(*O, [&](SubCommand &SC) { removeOption(O, &SC); });
287 }
288
289 bool hasOptions(const SubCommand &Sub) const {
292 }
293
294 bool hasOptions() const {
295 for (const auto *S : RegisteredSubCommands) {
296 if (hasOptions(*S))
297 return true;
298 }
299 return false;
300 }
301
302 bool hasNamedSubCommands() const {
303 for (const auto *S : RegisteredSubCommands)
304 if (!S->getName().empty())
305 return true;
306 return false;
307 }
308
309 SubCommand *getActiveSubCommand() { return ActiveSubCommand; }
310
313 if (!Sub.OptionsMap.insert(std::make_pair(NewName, O)).second) {
314 errs() << ProgramName << ": CommandLine Error: Option '" << O->ArgStr
315 << "' registered more than once!\n";
316 report_fatal_error("inconsistency in registered CommandLine options");
317 }
319 }
320
322 forEachSubCommand(*O,
323 [&](SubCommand &SC) { updateArgStr(O, NewName, &SC); });
324 }
325
326 void printOptionValues();
327
331 return cat->getName() == Category->getName();
332 }) == 0 &&
333 "Duplicate option categories");
334
335 RegisteredOptionCategories.insert(cat);
336 }
337
341 return (->getName().empty()) &&
343 }) == 0 &&
344 "Duplicate subcommands");
345 RegisteredSubCommands.insert(sub);
346
347
348
350 "SubCommand::getAll() should not be registered");
353 if ((O->isPositional() || O->isSink() || O->isConsumeAfter()) ||
354 O->hasArgStr())
355 addOption(O, sub);
356 else
357 addLiteralOption(*O, sub, E.first());
358 }
359 }
360
362 RegisteredSubCommands.erase(sub);
363 }
364
367 return make_range(RegisteredSubCommands.begin(),
368 RegisteredSubCommands.end());
369 }
370
371 void reset() {
372 ActiveSubCommand = nullptr;
373 ProgramName.clear();
375
376 MoreHelp.clear();
377 RegisteredOptionCategories.clear();
378
380 RegisteredSubCommands.clear();
381
385
386 DefaultOptions.clear();
387 }
388
389private:
390 SubCommand *ActiveSubCommand = nullptr;
391
394 bool LongOptionsUseDoubleDash, bool HaveDoubleDash) {
395 Option *Opt = LookupOption(Sub, Arg, Value);
396 if (Opt && LongOptionsUseDoubleDash && !HaveDoubleDash && (Opt))
397 return nullptr;
398 return Opt;
399 }
401};
402
403}
404
406
407template <typename T, T TrueVal, T FalseVal>
409 if (Arg == "" || Arg == "true" || Arg == "TRUE" || Arg == "True" ||
410 Arg == "1") {
412 return false;
413 }
414
415 if (Arg == "false" || Arg == "FALSE" || Arg == "False" || Arg == "0") {
416 Value = FalseVal;
417 return false;
418 }
419 return O.error("'" + Arg +
420 "' is invalid value for boolean argument! Try 0 or 1");
421}
422
425}
426
429}
430
433 FullyInitialized = true;
434}
435
437
439 if (FullyInitialized)
445}
446
448 assert(.empty() && "Categories cannot be empty.");
449
450
451
456}
457
459 NumOccurrences = 0;
463}
464
465void OptionCategory::registerCategory() {
467}
468
469
470
471
472
475
476
478
480
482
485}
486
489}
490
495
497}
498
499SubCommand::operator bool() const {
500 return (GlobalParser->getActiveSubCommand() == this);
501}
502
503
504
505
506
507
508
509
512
514 return nullptr;
516
517 size_t EqualPos = Arg.find('=');
518
519
521
523 }
524
525
526
527
530 return nullptr;
531
532 auto *O = I->second;
534 return nullptr;
535
537 Arg = Arg.substr(0, EqualPos);
538 return I->second;
539}
540
542 std::string &NearestString) {
543 if (Name.empty())
545
547 for (auto *S : RegisteredSubCommands) {
549 "SubCommand::getAll() is not expected in RegisteredSubCommands");
550 if (S->getName().empty())
551 continue;
552
553 if (S->getName() == Name)
554 return S;
555
556 if (!NearestMatch && S->getName().edit_distance(Name) < 2)
557 NearestMatch = S;
558 }
559
560 if (NearestMatch)
561 NearestString = NearestMatch->getName();
562
564}
565
566
567
568
569
572 std::string &NearestString) {
573
575 return nullptr;
576
577
578 std::pair<StringRef, StringRef> SplitArg = Arg.split('=');
579 StringRef &LHS = SplitArg.first;
581
582
583 Option *Best = nullptr;
584 unsigned BestDistance = 0;
586 ie = OptionsMap.end();
587 it != ie; ++it) {
588 Option *O = it->second;
589
590 if (O->getOptionHiddenFlag() == ReallyHidden)
591 continue;
592
594 O->getExtraOptionNames(OptionNames);
595 if (O->hasArgStr())
596 OptionNames.push_back(O->ArgStr);
597
600 for (const auto &Name : OptionNames) {
602 Flag, true, BestDistance);
603 if (!Best || Distance < BestDistance) {
604 Best = O;
605 BestDistance = Distance;
606 if (RHS.empty() || !PermitValue)
607 NearestString = std::string(Name);
608 else
609 NearestString = (Twine(Name) + "=" + RHS).str();
610 }
611 }
612 }
613
614 return Best;
615}
616
617
618
621 bool MultiArg = false) {
622
623
627
629
631 return true;
632
633 Val = Val.substr(Pos + 1);
634
635 Pos = Val.find(',');
636 }
637
639 }
640
642}
643
644
645
646
649 const char *const *argv, int &i) {
650
652
653
656 if (.data()) {
657
658
660 return Handler->error("requires a value!");
661
662 assert(argv && "null check");
664 }
665 break;
667 if (NumAdditionalVals > 0)
668 return Handler->error("multi-valued option specified"
669 " with ValueDisallowed modifier!");
670
671 if (Value.data())
672 return Handler->error("does not allow a value! '" + Twine(Value) +
673 "' specified.");
674 break;
676 break;
677 }
678
679
680 if (NumAdditionalVals == 0)
682
683
684 bool MultiArg = false;
685
686 if (Value.data()) {
688 return true;
689 --NumAdditionalVals;
690 MultiArg = true;
691 }
692
693 while (NumAdditionalVals > 0) {
694 if (i + 1 >= argc)
695 return Handler->error("not enough values!");
696 assert(argv && "null check");
698
700 return true;
701 MultiArg = true;
702 --NumAdditionalVals;
703 }
704 return false;
705}
706
708 int Dummy = i;
710}
711
712
713
714
715
716
717
719 bool (*Pred)(const Option *),
722 if (OMI != OptionsMap.end() && !Pred(OMI->getValue()))
723 OMI = OptionsMap.end();
724
725
726
727
728 while (OMI == OptionsMap.end() && Name.size() > 1) {
729 Name = Name.substr(0, Name.size() - 1);
731 if (OMI != OptionsMap.end() && !Pred(OMI->getValue()))
732 OMI = OptionsMap.end();
733 }
734
735 if (OMI != OptionsMap.end() && Pred(OMI->second)) {
737 return OMI->second;
738 }
739 return nullptr;
740}
741
742
743
744
745
748 bool &ErrorParsing,
750 if (Arg.size() == 1)
751 return nullptr;
752
753
756 if (!PGOpt)
757 return nullptr;
758
759 do {
763 assert(OptionsMap.count(Arg) && OptionsMap.find(Arg)->second == PGOpt);
764
765
766
769 Value = MaybeValue;
770 return PGOpt;
771 }
772
773 if (MaybeValue[0] == '=') {
775 return PGOpt;
776 }
777
778
780
781
783 ErrorParsing |= PGOpt->error("may not occur within a group!");
784 return nullptr;
785 }
786
787
788
789 int Dummy = 0;
791
792
793 Arg = MaybeValue;
795 } while (PGOpt);
796
797
798 return nullptr;
799}
800
802 return O->getNumOccurrencesFlag() == cl::Required ||
804}
805
807 return O->getNumOccurrencesFlag() == cl::ZeroOrMore ||
809}
810
812 return C == ' ' || C == '\t' || C == '\r' || C == '\n';
813}
814
817}
818
819static bool isQuote(char C) { return C == '\"' || C == '\''; }
820
823 bool MarkEOLs) {
825 for (size_t I = 0, E = Src.size(); I != E; ++I) {
826
827 if (Token.empty()) {
829
830 if (MarkEOLs && Src[I] == '\n')
832 ++I;
833 }
834 if (I == E)
835 break;
836 }
837
839
840
841 if (I + 1 < E && C == '\\') {
842 ++I;
844 continue;
845 }
846
847
849 ++I;
850 while (I != E && Src[I] != C) {
851
852 if (Src[I] == '\\' && I + 1 != E)
853 ++I;
855 ++I;
856 }
857 if (I == E)
858 break;
859 continue;
860 }
861
862
864 if (!Token.empty())
866
867 if (MarkEOLs && C == '\n')
870 continue;
871 }
872
873
875 }
876
877
878 if (!Token.empty())
880}
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
900 size_t E = Src.size();
901 int BackslashCount = 0;
902
903 do {
904 ++I;
905 ++BackslashCount;
906 } while (I != E && Src[I] == '\\');
907
908 bool FollowedByDoubleQuote = (I != E && Src[I] == '"');
909 if (FollowedByDoubleQuote) {
910 Token.append(BackslashCount / 2, '\\');
911 if (BackslashCount % 2 == 0)
912 return I - 1;
914 return I;
915 }
916 Token.append(BackslashCount, '\\');
917 return I - 1;
918}
919
920
921
922
925}
928}
929
930
931
934 bool AlwaysCopy, function_ref<void()> MarkEOL, bool InitialCommandName) {
936
937
938
939
940
941
942
943 bool CommandName = InitialCommandName;
944
945
946 enum { INIT, UNQUOTED, QUOTED } State = INIT;
947
948 for (size_t I = 0, E = Src.size(); I < E; ++I) {
949 switch (State) {
951 assert(Token.empty() && "token should be empty in initial state");
952
954 if (Src[I] == '\n')
955 MarkEOL();
956 ++I;
957 }
958
959 if (I >= E)
960 break;
961 size_t Start = I;
962 if (CommandName) {
964 ++I;
965 } else {
967 ++I;
968 }
969 StringRef NormalChars = Src.slice(Start, I);
971
972
973 AddToken(AlwaysCopy ? Saver.save(NormalChars) : NormalChars);
974 if (I < E && Src[I] == '\n') {
975 MarkEOL();
976 CommandName = InitialCommandName;
977 } else {
978 CommandName = false;
979 }
980 } else if (Src[I] == '\"') {
981 Token += NormalChars;
982 State = QUOTED;
983 } else if (Src[I] == '\\') {
984 assert(!CommandName && "or else we'd have treated it as a normal char");
985 Token += NormalChars;
987 State = UNQUOTED;
988 } else {
990 }
991 break;
992 }
993
994 case UNQUOTED:
996
997
998
999 AddToken(Saver.save(Token.str()));
1001 if (Src[I] == '\n') {
1002 CommandName = InitialCommandName;
1003 MarkEOL();
1004 } else {
1005 CommandName = false;
1006 }
1007 State = INIT;
1008 } else if (Src[I] == '\"') {
1009 State = QUOTED;
1010 } else if (Src[I] == '\\' && !CommandName) {
1012 } else {
1014 }
1015 break;
1016
1017 case QUOTED:
1018 if (Src[I] == '\"') {
1019 if (I < (E - 1) && Src[I + 1] == '"') {
1020
1021
1023 ++I;
1024 } else {
1025
1026 State = UNQUOTED;
1027 }
1028 } else if (Src[I] == '\\' && !CommandName) {
1030 } else {
1032 }
1033 break;
1034 }
1035 }
1036
1037 if (State != INIT)
1038 AddToken(Saver.save(Token.str()));
1039}
1040
1043 bool MarkEOLs) {
1044 auto AddToken = [&](StringRef Tok) { NewArgv.push_back(Tok.data()); };
1045 auto OnEOL = [&]() {
1046 if (MarkEOLs)
1048 };
1050 true, OnEOL, false);
1051}
1052
1056 auto OnEOL = []() {};
1058 OnEOL, false);
1059}
1060
1063 bool MarkEOLs) {
1064 auto AddToken = [&](StringRef Tok) { NewArgv.push_back(Tok.data()); };
1065 auto OnEOL = [&]() {
1066 if (MarkEOLs)
1068 };
1070 true, OnEOL, true);
1071}
1072
1075 bool MarkEOLs) {
1076 for (const char *Cur = Source.begin(); Cur != Source.end();) {
1078
1080 while (Cur != Source.end() && isWhitespace(*Cur))
1081 ++Cur;
1082 continue;
1083 }
1084 if (*Cur == '#') {
1085 while (Cur != Source.end() && *Cur != '\n')
1086 ++Cur;
1087 continue;
1088 }
1089
1090 const char *Start = Cur;
1091 for (const char *End = Source.end(); Cur != End; ++Cur) {
1092 if (*Cur == '\\') {
1093 if (Cur + 1 != End) {
1094 ++Cur;
1095 if (*Cur == '\n' ||
1096 (*Cur == '\r' && (Cur + 1 != End) && Cur[1] == '\n')) {
1097 Line.append(Start, Cur - 1);
1098 if (*Cur == '\r')
1099 ++Cur;
1100 Start = Cur + 1;
1101 }
1102 }
1103 } else if (*Cur == '\n')
1104 break;
1105 }
1106
1107 Line.append(Start, Cur);
1109 }
1110}
1111
1112
1113
1115 return (S.size() >= 3 && S[0] == '\xef' && S[1] == '\xbb' && S[2] == '\xbf');
1116}
1117
1118
1120 const char *&Arg) {
1124
1129 TokenPos = ArgString.find(Token, StartPos)) {
1130
1131
1132 const StringRef LHS = ArgString.substr(StartPos, TokenPos - StartPos);
1133 if (ResponseFile.empty())
1134 ResponseFile = LHS;
1135 else
1137 ResponseFile.append(BasePath);
1138 StartPos = TokenPos + Token.size();
1139 }
1140
1141 if (!ResponseFile.empty()) {
1142
1144 if (!Remaining.empty())
1146 Arg = Saver.save(ResponseFile.str()).data();
1147 }
1148}
1149
1150
1151Error ExpansionContext::expandResponseFile(
1156 if (!MemBufOrErr) {
1157 std::error_code EC = MemBufOrErr.getError();
1159 "': " + EC.message());
1160 }
1163
1164
1166 std::string UTF8Buf;
1170 "Could not convert UTF16 to UTF8");
1172 }
1173
1174
1175
1177 Str = StringRef(BufRef.data() + 3, BufRef.size() - 3);
1178
1179
1180 Tokenizer(Str, Saver, NewArgv, MarkEOLs);
1181
1182
1183
1184
1185 if (!RelativeNames && !InConfigFile)
1187
1189 for (const char *&Arg : NewArgv) {
1190 if (!Arg)
1191 continue;
1192
1193
1194 if (InConfigFile)
1196
1197
1198
1201 bool ConfigInclusion = false;
1202 if (ArgStr.consume_front("@")) {
1203 FileName = ArgStr;
1205 continue;
1206 } else if (ArgStr.consume_front("--config=")) {
1207 FileName = ArgStr;
1208 ConfigInclusion = true;
1209 } else {
1210 continue;
1211 }
1212
1213
1220 std::make_error_code(std::errc::no_such_file_or_directory),
1221 "cannot not find configuration file: " + FileName);
1222 ResponseFile.append(FilePath);
1223 } else {
1224 ResponseFile.append(BasePath);
1226 }
1227 Arg = Saver.save(ResponseFile.str()).data();
1228 }
1230}
1231
1232
1233
1236 struct ResponseFileRecord {
1237 std::string File;
1238 size_t End;
1239 };
1240
1241
1242
1243
1245
1246
1247
1249
1250
1251 for (unsigned I = 0; I != Argv.size();) {
1252 while (I == FileStack.back().End) {
1253
1254
1256 }
1257
1258 const char *Arg = Argv[I];
1259
1260 if (Arg == nullptr) {
1261 ++I;
1262 continue;
1263 }
1264
1265 if (Arg[0] != '@') {
1266 ++I;
1267 continue;
1268 }
1269
1270 const char *FName = Arg + 1;
1271
1272
1275 if (CurrentDir.empty()) {
1277 CurrDir = *CWD;
1278 } else {
1280 CWD.getError(), Twine("cannot get absolute path for: ") + FName);
1281 }
1282 } else {
1283 CurrDir = CurrentDir;
1284 }
1286 FName = CurrDir.c_str();
1287 }
1288
1290 if (!Res || !Res->exists()) {
1291 std::error_code EC = Res.getError();
1292 if (!InConfigFile) {
1293
1294
1296 ++I;
1297 continue;
1298 }
1299 }
1300 if (!EC)
1303 "': " + EC.message());
1304 }
1306
1307 auto IsEquivalent =
1308 [FileStatus, this](const ResponseFileRecord &RFile) -> ErrorOr {
1310 if ()
1311 return RHS.getError();
1313 };
1314
1315
1316 for (const auto &F : drop_begin(FileStack)) {
1318 if (R.get())
1320 R.getError(), Twine("recursive expansion of: '") + F.File + "'");
1321 } else {
1323 Twine("cannot open file: ") + F.File);
1324 }
1325 }
1326
1327
1328
1330 if (Error Err = expandResponseFile(FName, ExpandedArgv))
1331 return Err;
1332
1333 for (ResponseFileRecord &Record : FileStack) {
1334
1335
1336 Record.End += ExpandedArgv.size() - 1;
1337 }
1338
1339 FileStack.push_back({FName, I + ExpandedArgv.size()});
1342 }
1343
1344
1345
1346
1347
1348
1349 assert(FileStack.size() > 0 && Argv.size() == FileStack.back().End);
1351}
1352
1356#ifdef _WIN32
1358#else
1360#endif
1361
1362 if (EnvVar)
1364 Tokenize(*EnvValue, Saver, NewArgv, false);
1365
1366
1367 NewArgv.append(Argv + 1, Argv + Argc);
1371 return false;
1372 }
1373 return true;
1374}
1375
1381 return false;
1382 }
1383 return true;
1384}
1385
1387 : Saver(A), Tokenizer(T), FS(vfs::getRealFileSystem().get()) {}
1388
1392 const auto FileExists = [this](SmallString<128> Path) -> bool {
1396 };
1397
1398
1399
1401 CfgFilePath = FileName;
1403 return false;
1404 if (!FileExists(CfgFilePath))
1405 return false;
1406 FilePath.assign(CfgFilePath.begin(), CfgFilePath.end());
1407 return true;
1408 }
1409
1410
1411 for (const StringRef &Dir : SearchDirs) {
1412 if (Dir.empty())
1413 continue;
1414 CfgFilePath.assign(Dir);
1417 if (FileExists(CfgFilePath)) {
1418 FilePath.assign(CfgFilePath.begin(), CfgFilePath.end());
1419 return true;
1420 }
1421 }
1422
1423 return false;
1424}
1425
1430 AbsPath.assign(CfgFile);
1431 if (std::error_code EC = FS->makeAbsolute(AbsPath))
1432 return make_error(
1433 EC, Twine("cannot get absolute path for " + CfgFile));
1434 CfgFile = AbsPath.str();
1435 }
1436 InConfigFile = true;
1437 RelativeNames = true;
1438 if (Error Err = expandResponseFile(CfgFile, Argv))
1439 return Err;
1441}
1442
1446 const char *EnvVar,
1447 bool LongOptionsUseDoubleDash) {
1453
1454
1455 if (EnvVar) {
1456 if (std::optionalstd::string EnvValue =
1459 }
1460
1461
1462 for (int I = 1; I < argc; ++I)
1464 int NewArgc = static_cast<int>(NewArgv.size());
1465
1466
1467 return GlobalParser->ParseCommandLineOptions(NewArgc, &NewArgv[0], Overview,
1468 Errs, LongOptionsUseDoubleDash);
1469}
1470
1471
1472void CommandLineParser::ResetAllOptionOccurrences() {
1473
1474
1475
1476 for (auto *SC : RegisteredSubCommands) {
1477 for (auto &O : SC->OptionsMap)
1478 O.second->reset();
1479 for (Option *O : SC->PositionalOpts)
1480 O->reset();
1481 for (Option *O : SC->SinkOpts)
1482 O->reset();
1483 if (SC->ConsumeAfterOpt)
1484 SC->ConsumeAfterOpt->reset();
1485 }
1486}
1487
1488bool CommandLineParser::ParseCommandLineOptions(int argc,
1489 const char *const *argv,
1492 bool LongOptionsUseDoubleDash) {
1493 assert(hasOptions() && "No options specified!");
1494
1495 ProgramOverview = Overview;
1496 bool IgnoreErrors = Errs;
1497 if (!Errs)
1498 Errs = &errs();
1499 bool ErrorParsing = false;
1500
1501
1504#ifdef _WIN32
1506#else
1508#endif
1510 if (Error Err = ECtx.expandResponseFiles(newArgv)) {
1511 *Errs << toString(std::move(Err)) << '\n';
1512 return false;
1513 }
1514 argv = &newArgv[0];
1515 argc = static_cast<int>(newArgv.size());
1516
1517
1519
1520
1521 unsigned NumPositionalRequired = 0;
1522
1523
1524 bool HasUnlimitedPositionals = false;
1525
1526 int FirstArg = 1;
1528 std::string NearestSubCommandString;
1529 bool MaybeNamedSubCommand =
1530 argc >= 2 && argv[FirstArg][0] != '-' && hasNamedSubCommands();
1531 if (MaybeNamedSubCommand) {
1532
1533
1534 ChosenSubCommand =
1535 LookupSubCommand(StringRef(argv[FirstArg]), NearestSubCommandString);
1537 FirstArg = 2;
1538 }
1539 GlobalParser->ActiveSubCommand = ChosenSubCommand;
1540
1541 assert(ChosenSubCommand);
1542 auto &ConsumeAfterOpt = ChosenSubCommand->ConsumeAfterOpt;
1543 auto &PositionalOpts = ChosenSubCommand->PositionalOpts;
1544 auto &SinkOpts = ChosenSubCommand->SinkOpts;
1545 auto &OptionsMap = ChosenSubCommand->OptionsMap;
1546
1547 for (auto *O: DefaultOptions) {
1548 addOption(O, true);
1549 }
1550
1551 if (ConsumeAfterOpt) {
1552 assert(PositionalOpts.size() > 0 &&
1553 "Cannot specify cl::ConsumeAfter without a positional argument!");
1554 }
1555 if (!PositionalOpts.empty()) {
1556
1557
1558 bool UnboundedFound = false;
1559 for (size_t i = 0, e = PositionalOpts.size(); i != e; ++i) {
1560 Option *Opt = PositionalOpts[i];
1562 ++NumPositionalRequired;
1563 else if (ConsumeAfterOpt) {
1564
1565
1566 if (PositionalOpts.size() > 1) {
1567 if (!IgnoreErrors)
1568 Opt->error("error - this positional option will never be matched, "
1569 "because it does not Require a value, and a "
1570 "cl::ConsumeAfter option is active!");
1571 ErrorParsing = true;
1572 }
1573 } else if (UnboundedFound && !Opt->hasArgStr()) {
1574
1575
1576
1577
1578 if (!IgnoreErrors)
1579 Opt->error("error - option can never match, because "
1580 "another positional argument will match an "
1581 "unbounded number of values, and this option"
1582 " does not require a value!");
1583 *Errs << ProgramName << ": CommandLine Error: Option '" << Opt->ArgStr
1584 << "' is all messed up!\n";
1585 *Errs << PositionalOpts.size();
1586 ErrorParsing = true;
1587 }
1589 }
1590 HasUnlimitedPositionals = UnboundedFound || ConsumeAfterOpt;
1591 }
1592
1593
1594
1595
1597
1598
1599
1600
1601 Option *ActivePositionalArg = nullptr;
1602
1603
1604 bool DashDashFound = false;
1605 for (int i = FirstArg; i < argc; ++i) {
1606 Option *Handler = nullptr;
1607 std::string NearestHandlerString;
1610 bool HaveDoubleDash = false;
1611
1612
1613
1614
1615
1616 if (argv[i][0] != '-' || argv[i][1] == 0 || DashDashFound) {
1617
1618 if (ActivePositionalArg) {
1620 continue;
1621 }
1622
1623 if (!PositionalOpts.empty()) {
1625
1626
1627
1628
1629 if (PositionalVals.size() >= NumPositionalRequired && ConsumeAfterOpt) {
1630 for (++i; i < argc; ++i)
1632 break;
1633 }
1634
1635
1636 continue;
1637 }
1638 } else if (argv[i][0] == '-' && argv[i][1] == '-' && argv[i][2] == 0 &&
1639 !DashDashFound) {
1640 DashDashFound = true;
1641 continue;
1642 } else if (ActivePositionalArg &&
1644
1645
1646
1647 ArgName = StringRef(argv[i] + 1);
1648
1650 HaveDoubleDash = true;
1651
1652 Handler = LookupLongOption(*ChosenSubCommand, ArgName, Value,
1653 LongOptionsUseDoubleDash, HaveDoubleDash);
1656 continue;
1657 }
1658 } else {
1659 ArgName = StringRef(argv[i] + 1);
1660
1662 HaveDoubleDash = true;
1663
1664 Handler = LookupLongOption(*ChosenSubCommand, ArgName, Value,
1665 LongOptionsUseDoubleDash, HaveDoubleDash);
1666
1667
1668
1669
1672 LongOptionsUseDoubleDash, HaveDoubleDash);
1673
1674
1675 if (!Handler && !(LongOptionsUseDoubleDash && HaveDoubleDash))
1677 OptionsMap);
1678
1679
1680
1681 if (!Handler && SinkOpts.empty())
1683 }
1684
1685 if (!Handler) {
1686 if (!SinkOpts.empty()) {
1687 for (Option *SinkOpt : SinkOpts)
1688 SinkOpt->addOccurrence(i, "", StringRef(argv[i]));
1689 continue;
1690 }
1691
1692 auto ReportUnknownArgument = [&](bool IsArg,
1693 StringRef NearestArgumentName) {
1694 *Errs << ProgramName << ": Unknown "
1695 << (IsArg ? "command line argument" : "subcommand") << " '"
1696 << argv[i] << "'. Try: '" << argv[0] << " --help'\n";
1697
1698 if (NearestArgumentName.empty())
1699 return;
1700
1701 *Errs << ProgramName << ": Did you mean '";
1702 if (IsArg)
1703 *Errs << PrintArg(NearestArgumentName, 0);
1704 else
1705 *Errs << NearestArgumentName;
1706 *Errs << "'?\n";
1707 };
1708
1709 if (i > 1 || !MaybeNamedSubCommand)
1710 ReportUnknownArgument(true, NearestHandlerString);
1711 else
1712 ReportUnknownArgument(false, NearestSubCommandString);
1713
1714 ErrorParsing = true;
1715 continue;
1716 }
1717
1718
1719
1722 Handler->error("This argument does not take a value.\n"
1723 "\tInstead, it consumes any positional arguments until "
1724 "the next recognized option.", *Errs);
1725 ErrorParsing = true;
1726 }
1727 ActivePositionalArg = Handler;
1728 }
1729 else
1730 ErrorParsing |= ProvideOption(Handler, ArgName, Value, argc, argv, i);
1731 }
1732
1733
1734 if (NumPositionalRequired > PositionalVals.size()) {
1735 *Errs << ProgramName
1736 << ": Not enough positional command line arguments specified!\n"
1737 << "Must specify at least " << NumPositionalRequired
1738 << " positional argument" << (NumPositionalRequired > 1 ? "s" : "")
1739 << ": See: " << argv[0] << " --help\n";
1740
1741 ErrorParsing = true;
1742 } else if (!HasUnlimitedPositionals &&
1743 PositionalVals.size() > PositionalOpts.size()) {
1744 *Errs << ProgramName << ": Too many positional arguments specified!\n"
1745 << "Can specify at most " << PositionalOpts.size()
1746 << " positional arguments: See: " << argv[0] << " --help\n";
1747 ErrorParsing = true;
1748
1749 } else if (!ConsumeAfterOpt) {
1750
1751 unsigned ValNo = 0, NumVals = static_cast<unsigned>(PositionalVals.size());
1752 for (Option *Opt : PositionalOpts) {
1755 PositionalVals[ValNo].second);
1756 ValNo++;
1757 --NumPositionalRequired;
1758 }
1759
1760
1761
1762
1763
1765 while (NumVals - ValNo > NumPositionalRequired && ) {
1768 Done = true;
1769 [[fallthrough]];
1770 case cl::ZeroOrMore:
1771 case cl::OneOrMore:
1773 PositionalVals[ValNo].second);
1774 ValNo++;
1775 break;
1776 default:
1777 llvm_unreachable("Internal error, unexpected NumOccurrences flag in "
1778 "positional argument processing!");
1779 }
1780 }
1781 }
1782 } else {
1783 assert(ConsumeAfterOpt && NumPositionalRequired <= PositionalVals.size());
1784 unsigned ValNo = 0;
1785 for (Option *Opt : PositionalOpts)
1788 Opt, PositionalVals[ValNo].first, PositionalVals[ValNo].second);
1789 ValNo++;
1790 }
1791
1792
1793
1794
1795
1796
1797 if (PositionalOpts.size() == 1 && ValNo == 0 && !PositionalVals.empty()) {
1799 PositionalVals[ValNo].first,
1800 PositionalVals[ValNo].second);
1801 ValNo++;
1802 }
1803
1804
1805
1806 for (; ValNo != PositionalVals.size(); ++ValNo)
1807 ErrorParsing |=
1809 PositionalVals[ValNo].second);
1810 }
1811
1812
1813 for (const auto &Opt : OptionsMap) {
1818 Opt.second->error("must be specified at least once!");
1819 ErrorParsing = true;
1820 }
1821 [[fallthrough]];
1822 default:
1823 break;
1824 }
1825 }
1826
1827
1828
1829
1831 for (int i = 0; i < argc; ++i) dbgs() << argv[i] << ' ';
1832 dbgs() << '\n';);
1833
1834
1835
1836 MoreHelp.clear();
1837
1838
1839 if (ErrorParsing) {
1840 if (!IgnoreErrors)
1841 exit(1);
1842 return false;
1843 }
1844 return true;
1845}
1846
1847
1848
1849
1850
1852 if (!ArgName.data())
1854 if (ArgName.empty())
1855 Errs << HelpStr;
1856 else
1857 Errs << GlobalParser->ProgramName << ": for the " << PrintArg(ArgName, 0);
1858
1859 Errs << " option: " << Message << "\n";
1860 return true;
1861}
1862
1864 bool MultiArg) {
1865 if (!MultiArg)
1866 NumOccurrences++;
1867
1868 return handleOccurrence(pos, ArgName, Value);
1869}
1870
1871
1872
1873
1875 if (O.ValueStr.empty())
1876 return DefaultMsg;
1877 return O.ValueStr;
1878}
1879
1880
1881
1882
1883
1884
1885size_t alias::getOptionWidth() const {
1887}
1888
1890 size_t FirstLineIndentedBy) {
1891 assert(Indent >= FirstLineIndentedBy);
1892 std::pair<StringRef, StringRef> Split = HelpStr.split('\n');
1893 outs().indent(Indent - FirstLineIndentedBy)
1895 while (!Split.second.empty()) {
1896 Split = Split.second.split('\n');
1897 outs().indent(Indent) << Split.first << "\n";
1898 }
1899}
1900
1902 size_t FirstLineIndentedBy) {
1903 const StringRef ValHelpPrefix = " ";
1904 assert(BaseIndent >= FirstLineIndentedBy);
1905 std::pair<StringRef, StringRef> Split = HelpStr.split('\n');
1906 outs().indent(BaseIndent - FirstLineIndentedBy)
1907 << ArgHelpPrefix << ValHelpPrefix << Split.first << "\n";
1908 while (!Split.second.empty()) {
1909 Split = Split.second.split('\n');
1910 outs().indent(BaseIndent + ValHelpPrefix.size()) << Split.first << "\n";
1911 }
1912}
1913
1914
1915void alias::printOptionInfo(size_t GlobalWidth) const {
1918}
1919
1920
1921
1922
1923
1924
1925
1926
1927
1931 if (!ValName.empty()) {
1932 size_t FormattingLen = 3;
1934 FormattingLen = 6;
1936 }
1937
1938 return Len;
1939}
1940
1941
1942
1943
1945 size_t GlobalWidth) const {
1946 outs() << PrintArg(O.ArgStr);
1947
1949 if (!ValName.empty()) {
1952 } else if (O.getValueExpectedFlag() == ValueOptional)
1954 else {
1955 outs() << (O.ArgStr.size() == 1 ? " <" : "=<") << getValueStr(O, ValName)
1956 << '>';
1957 }
1958 }
1959
1961}
1962
1964 size_t GlobalWidth) const {
1965 outs() << PrintArg(O.ArgStr);
1966 outs().indent(GlobalWidth - O.ArgStr.size());
1967}
1968
1969
1970
1973 return parseBool<bool, true, false>(O, ArgName, Arg, Value);
1974}
1975
1976
1977
1980 return parseBool<boolOrDefault, BOU_TRUE, BOU_FALSE>(O, ArgName, Arg, Value);
1981}
1982
1983
1984
1988 return O.error("'" + Arg + "' value invalid for integer argument!");
1989 return false;
1990}
1991
1992
1993
1997 return O.error("'" + Arg + "' value invalid for long argument!");
1998 return false;
1999}
2000
2001
2002
2004 long long &Value) {
2006 return O.error("'" + Arg + "' value invalid for llong argument!");
2007 return false;
2008}
2009
2010
2011
2013 unsigned &Value) {
2014
2016 return O.error("'" + Arg + "' value invalid for uint argument!");
2017 return false;
2018}
2019
2020
2021
2023 unsigned long &Value) {
2024
2026 return O.error("'" + Arg + "' value invalid for ulong argument!");
2027 return false;
2028}
2029
2030
2031
2034 unsigned long long &Value) {
2035
2037 return O.error("'" + Arg + "' value invalid for ullong argument!");
2038 return false;
2039}
2040
2041
2042
2044 if (to_float(Arg, Value))
2045 return false;
2046 return O.error("'" + Arg + "' value invalid for floating point argument!");
2047}
2048
2050 double &Val) {
2052}
2053
2055 float &Val) {
2056 double dVal;
2058 return true;
2059 Val = (float)dVal;
2060 return false;
2061}
2062
2063
2064
2065
2066
2067
2068
2071
2072 for (unsigned i = 0; i != e; ++i) {
2074 return i;
2075 }
2076 return e;
2077}
2078
2084}
2085
2088 return O.getValueExpectedFlag() != ValueOptional || .empty() ||
2089 !Description.empty();
2090}
2091
2092
2094 if (O.hasArgStr()) {
2095 size_t Size =
2097 for (unsigned i = 0, e = getNumOptions(); i != e; ++i) {
2100 continue;
2103 }
2104 return Size;
2105 } else {
2106 size_t BaseSize = 0;
2107 for (unsigned i = 0, e = getNumOptions(); i != e; ++i)
2108 BaseSize = std::max(BaseSize, getOption(i).size() + 8);
2109 return BaseSize;
2110 }
2111}
2112
2113
2114
2115
2117 size_t GlobalWidth) const {
2118 if (O.hasArgStr()) {
2119
2120
2121 if (O.getValueExpectedFlag() == ValueOptional) {
2122 for (unsigned i = 0, e = getNumOptions(); i != e; ++i) {
2124 outs() << PrintArg(O.ArgStr);
2127 break;
2128 }
2129 }
2130 }
2131
2132 outs() << PrintArg(O.ArgStr) << EqValue;
2136 for (unsigned i = 0, e = getNumOptions(); i != e; ++i) {
2140 continue;
2143 if (OptionName.empty()) {
2147 }
2148 if (!Description.empty())
2150 else
2151 outs() << '\n';
2152 }
2153 } else {
2154 if (!O.HelpStr.empty())
2155 outs() << " " << O.HelpStr << '\n';
2156 for (unsigned i = 0, e = getNumOptions(); i != e; ++i) {
2160 }
2161 }
2162}
2163
2164static const size_t MaxOptWidth = 8;
2165
2166
2167
2168
2172 outs() << " " << PrintArg(O.ArgStr);
2173 outs().indent(GlobalWidth - O.ArgStr.size());
2174
2176 for (unsigned i = 0; i != NumOpts; ++i) {
2178 continue;
2179
2183 outs().indent(NumSpaces) << " (default: ";
2184 for (unsigned j = 0; j != NumOpts; ++j) {
2186 continue;
2188 break;
2189 }
2190 outs() << ")\n";
2191 return;
2192 }
2193 outs() << "= *unknown option value*\n";
2194}
2195
2196
2197
2198#define PRINT_OPT_DIFF(T) \
2199 void parser::printOptionDiff(const Option &O, T V, OptionValue D, \
2200 size_t GlobalWidth) const { \
2201 printOptionName(O, GlobalWidth); \
2202 std::string Str; \
2203 { \
2204 raw_string_ostream SS(Str); \
2205 SS << V; \
2206 } \
2207 outs() << "= " << Str; \
2208 size_t NumSpaces = \
2209 MaxOptWidth > Str.size() ? MaxOptWidth - Str.size() : 0; \
2210 outs().indent(NumSpaces) << " (default: "; \
2211 if (D.hasValue()) \
2212 outs() << D.getValue(); \
2213 else \
2214 outs() << "*no default*"; \
2215 outs() << ")\n"; \
2216 }
2217
2229
2232 size_t GlobalWidth) const {
2233 printOptionName(O, GlobalWidth);
2234 outs() << "= " << V;
2236 outs().indent(NumSpaces) << " (default: ";
2237 if (D.hasValue())
2239 else
2240 outs() << "*no default*";
2241 outs() << ")\n";
2242}
2243
2244
2246 size_t GlobalWidth) const {
2248 outs() << "= *cannot print option value*\n";
2249}
2250
2251
2252
2253
2254
2255static int OptNameCompare(const std::pair<const char *, Option *> *LHS,
2256 const std::pair<const char *, Option *> *RHS) {
2257 return strcmp(LHS->first, RHS->first);
2258}
2259
2260static int SubNameCompare(const std::pair<const char *, SubCommand *> *LHS,
2261 const std::pair<const char *, SubCommand *> *RHS) {
2262 return strcmp(LHS->first, RHS->first);
2263}
2264
2265
2267 SmallVectorImpl<std::pair<const char *, Option *>> &Opts,
2268 bool ShowHidden) {
2270
2273
2274 if (I->second->getOptionHiddenFlag() == ReallyHidden)
2275 continue;
2276
2277
2278 if (I->second->getOptionHiddenFlag() == Hidden && !ShowHidden)
2279 continue;
2280
2281
2282 if (!OptionSet.insert(I->second).second)
2283 continue;
2284
2285 Opts.push_back(
2286 std::pair<const char *, Option *>(I->getKey().data(), I->second));
2287 }
2288
2289
2291}
2292
2293static void
2295 SmallVectorImpl<std::pair<const char *, SubCommand *>> &Subs) {
2296 for (auto *S : SubMap) {
2297 if (S->getName().empty())
2298 continue;
2299 Subs.push_back(std::make_pair(S->getName().data(), S));
2300 }
2302}
2303
2304namespace {
2305
2306class HelpPrinter {
2307protected:
2308 const bool ShowHidden;
2310 StrOptionPairVector;
2312 StrSubCommandPairVector;
2313
2314 virtual void printOptions(StrOptionPairVector &Opts, size_t MaxArgLen) {
2315 for (size_t i = 0, e = Opts.size(); i != e; ++i)
2316 Opts[i].second->printOptionInfo(MaxArgLen);
2317 }
2318
2319 void printSubCommands(StrSubCommandPairVector &Subs, size_t MaxSubLen) {
2320 for (const auto &S : Subs) {
2321 outs() << " " << S.first;
2322 if (!S.second->getDescription().empty()) {
2323 outs().indent(MaxSubLen - strlen(S.first));
2324 outs() << " - " << S.second->getDescription();
2325 }
2326 outs() << "\n";
2327 }
2328 }
2329
2330public:
2331 explicit HelpPrinter(bool showHidden) : ShowHidden(showHidden) {}
2332 virtual ~HelpPrinter() = default;
2333
2334
2335 void operator=(bool Value) {
2337 return;
2338 printHelp();
2339
2340
2341 exit(0);
2342 }
2343
2344 void printHelp() {
2349
2350 StrOptionPairVector Opts;
2351 sortOpts(OptionsMap, Opts, ShowHidden);
2352
2353 StrSubCommandPairVector Subs;
2355
2357 outs() << "OVERVIEW: " << GlobalParser->ProgramOverview << "\n";
2358
2361 if (!Subs.empty())
2362 outs() << " [subcommand]";
2363 outs() << " [options]";
2364 } else {
2366 outs() << "SUBCOMMAND '" << Sub->getName()
2368 }
2370 << " [options]";
2371 }
2372
2373 for (auto *Opt : PositionalOpts) {
2377 }
2378
2379
2380 if (ConsumeAfterOpt)
2381 outs() << " " << ConsumeAfterOpt->HelpStr;
2382
2384
2385 size_t MaxSubLen = 0;
2386 for (size_t i = 0, e = Subs.size(); i != e; ++i)
2387 MaxSubLen = std::max(MaxSubLen, strlen(Subs[i].first));
2388
2389 outs() << "\n\n";
2390 outs() << "SUBCOMMANDS:\n\n";
2391 printSubCommands(Subs, MaxSubLen);
2392 outs() << "\n";
2394 << " --help\" to get more help on a specific "
2395 "subcommand";
2396 }
2397
2398 outs() << "\n\n";
2399
2400
2401 size_t MaxArgLen = 0;
2402 for (size_t i = 0, e = Opts.size(); i != e; ++i)
2403 MaxArgLen = std::max(MaxArgLen, Opts[i].second->getOptionWidth());
2404
2405 outs() << "OPTIONS:\n";
2406 printOptions(Opts, MaxArgLen);
2407
2408
2412 }
2413};
2414
2415class CategorizedHelpPrinter : public HelpPrinter {
2416public:
2417 explicit CategorizedHelpPrinter(bool showHidden) : HelpPrinter(showHidden) {}
2418
2419
2420
2421
2422
2423 static int OptionCategoryCompare(OptionCategory *const *A,
2425 return (*A)->getName().compare((*B)->getName());
2426 }
2427
2428
2429 using HelpPrinter::operator=;
2430
2431protected:
2432 void printOptions(StrOptionPairVector &Opts, size_t MaxArgLen) override {
2433 std::vector<OptionCategory *> SortedCategories;
2435
2436
2437
2439 SortedCategories.push_back(Category);
2440
2441
2442 assert(SortedCategories.size() > 0 && "No option categories registered!");
2443 array_pod_sort(SortedCategories.begin(), SortedCategories.end(),
2444 OptionCategoryCompare);
2445
2446
2447
2448
2449 for (size_t I = 0, E = Opts.size(); I != E; ++I) {
2450 Option *Opt = Opts[I].second;
2453 "Option has an unregistered category");
2454 CategorizedOptions[Cat].push_back(Opt);
2455 }
2456 }
2457
2458
2460
2461 const auto &CategoryOptions = CategorizedOptions[Category];
2462 if (CategoryOptions.empty())
2463 continue;
2464
2465
2466 outs() << "\n";
2468
2469
2472 else
2473 outs() << "\n";
2474
2475
2476 for (const Option *Opt : CategoryOptions)
2478 }
2479 }
2480};
2481
2482
2483
2484class HelpPrinterWrapper {
2485private:
2486 HelpPrinter &UncategorizedPrinter;
2487 CategorizedHelpPrinter &CategorizedPrinter;
2488
2489public:
2490 explicit HelpPrinterWrapper(HelpPrinter &UncategorizedPrinter,
2491 CategorizedHelpPrinter &CategorizedPrinter)
2492 : UncategorizedPrinter(UncategorizedPrinter),
2493 CategorizedPrinter(CategorizedPrinter) {}
2494
2495
2496 void operator=(bool Value);
2497};
2498
2499}
2500
2501#if defined(__GNUC__)
2502
2503
2504# if defined(__OPTIMIZE__)
2505# define LLVM_IS_DEBUG_BUILD 0
2506# else
2507# define LLVM_IS_DEBUG_BUILD 1
2508# endif
2509#elif defined(_MSC_VER)
2510
2511
2512
2513# if defined(_DEBUG)
2514# define LLVM_IS_DEBUG_BUILD 1
2515# else
2516# define LLVM_IS_DEBUG_BUILD 0
2517# endif
2518#else
2519
2520# define LLVM_IS_DEBUG_BUILD 0
2521#endif
2522
2523namespace {
2524class VersionPrinter {
2525public:
2526 void print(std::vector ExtraPrinters = {}) {
2528#ifdef PACKAGE_VENDOR
2529 OS << PACKAGE_VENDOR << " ";
2530#else
2531 OS << "LLVM (http://llvm.org/):\\n ";
2532#endif
2533 OS << PACKAGE_NAME << " version " << PACKAGE_VERSION << "\n ";
2534#if LLVM_IS_DEBUG_BUILD
2535 OS << "DEBUG build";
2536#else
2537 OS << "Optimized build";
2538#endif
2539#ifndef NDEBUG
2540 OS << " with assertions";
2541#endif
2542 OS << ".\n";
2543
2544
2545
2546 if (!ExtraPrinters.empty()) {
2547 for (const auto &I : ExtraPrinters)
2549 }
2550 }
2551 void operator=(bool OptionWasSpecified);
2552};
2553
2554struct CommandLineCommonOptions {
2555
2556
2557 HelpPrinter UncategorizedNormalPrinter{false};
2558 HelpPrinter UncategorizedHiddenPrinter{true};
2559 CategorizedHelpPrinter CategorizedNormalPrinter{false};
2560 CategorizedHelpPrinter CategorizedHiddenPrinter{true};
2561
2562
2563 HelpPrinterWrapper WrappedNormalPrinter{UncategorizedNormalPrinter,
2564 CategorizedNormalPrinter};
2565 HelpPrinterWrapper WrappedHiddenPrinter{UncategorizedHiddenPrinter,
2566 CategorizedHiddenPrinter};
2567
2569
2570
2571
2572
2574 "help-list",
2576 "Display list of available options (--help-list-hidden for more)"),
2580 cl::cat(GenericCategory),
2582
2584 "help-list-hidden",
2585 cl::desc("Display list of all available options"),
2589 cl::cat(GenericCategory),
2591
2592
2593
2594
2596 "help",
2597 cl::desc("Display available options (--help-hidden for more)"),
2600 cl::cat(GenericCategory),
2602
2605
2607 "help-hidden",
2608 cl::desc("Display all available options"),
2612 cl::cat(GenericCategory),
2614
2616 "print-options",
2617 cl::desc("Print non-default options after command line parsing"),
2620 cl::cat(GenericCategory),
2622
2624 "print-all-options",
2625 cl::desc("Print all option values after command line parsing"),
2628 cl::cat(GenericCategory),
2630
2632
2633 std::vector ExtraVersionPrinters;
2634
2635
2636 VersionPrinter VersionPrinterInstance;
2637
2639 "version", cl::desc("Display the version of this program"),
2641 cl::cat(GenericCategory)};
2642};
2643}
2644
2645
2646
2648
2660}
2661
2663
2664 static OptionCategory GeneralCategory{"General options"};
2665 return GeneralCategory;
2666}
2667
2668void VersionPrinter::operator=(bool OptionWasSpecified) {
2669 if (!OptionWasSpecified)
2670 return;
2671
2672 if (CommonOptions->OverrideVersionPrinter != nullptr) {
2674 exit(0);
2675 }
2677
2678 exit(0);
2679}
2680
2681void HelpPrinterWrapper::operator=(bool Value) {
2683 return;
2684
2685
2686
2687
2688 if (GlobalParser->RegisteredOptionCategories.size() > 1) {
2689
2690
2692
2693 CategorizedPrinter = true;
2694 } else
2695 UncategorizedPrinter = true;
2696}
2697
2698
2700
2701void CommandLineParser::printOptionValues() {
2703 return;
2704
2707
2708
2709 size_t MaxArgLen = 0;
2710 for (size_t i = 0, e = Opts.size(); i != e; ++i)
2711 MaxArgLen = std::max(MaxArgLen, Opts[i].second->getOptionWidth());
2712
2713 for (size_t i = 0, e = Opts.size(); i != e; ++i)
2714 Opts[i].second->printOptionValue(MaxArgLen, CommonOptions->PrintAllOptions);
2715}
2716
2717
2719 if ( && !Categorized)
2720 CommonOptions->UncategorizedNormalPrinter.printHelp();
2721 else if ( && Categorized)
2722 CommonOptions->CategorizedNormalPrinter.printHelp();
2723 else if (Hidden && !Categorized)
2724 CommonOptions->UncategorizedHiddenPrinter.printHelp();
2725 else
2726 CommonOptions->CategorizedHiddenPrinter.printHelp();
2727}
2728
2731
2732
2733 "",
2734
2735#if LLVM_IS_DEBUG_BUILD
2736 "+unoptimized",
2737#endif
2738#ifndef NDEBUG
2739 "+assertions",
2740#endif
2741#ifdef EXPENSIVE_CHECKS
2742 "+expensive-checks",
2743#endif
2744#if __has_feature(address_sanitizer)
2745 "+asan",
2746#endif
2747#if __has_feature(dataflow_sanitizer)
2748 "+dfsan",
2749#endif
2750#if __has_feature(hwaddress_sanitizer)
2751 "+hwasan",
2752#endif
2753#if __has_feature(memory_sanitizer)
2754 "+msan",
2755#endif
2756#if __has_feature(thread_sanitizer)
2757 "+tsan",
2758#endif
2759#if __has_feature(undefined_behavior_sanitizer)
2760 "+ubsan",
2761#endif
2762 };
2764}
2765
2766
2768#if LLVM_VERSION_PRINTER_SHOW_BUILD_CONFIG
2769 OS << "Build config: ";
2771 OS << '\n';
2772#endif
2773}
2774
2775
2778}
2779
2782}
2783
2786}
2787
2790 auto &Subs = GlobalParser->RegisteredSubCommands;
2791 (void)Subs;
2792 assert(Subs.contains(&Sub));
2794}
2795
2798 return GlobalParser->getRegisteredSubcommands();
2799}
2800
2804 bool Unrelated = true;
2805 for (auto &Cat : I.second->Categories) {
2806 if (Cat == &Category || Cat == &CommonOptions->GenericCategory)
2807 Unrelated = false;
2808 }
2809 if (Unrelated)
2811 }
2812}
2813
2818 bool Unrelated = true;
2819 for (auto &Cat : I.second->Categories) {
2822 Unrelated = false;
2823 }
2824 if (Unrelated)
2826 }
2827}
2828
2832}
2833
2835 const char *Overview) {
2838}
This file defines the StringMap class.
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static bool CommaSeparateAndAddOccurrence(Option *Handler, unsigned pos, StringRef ArgName, StringRef Value, bool MultiArg=false)
CommaSeparateAndAddOccurrence - A wrapper around Handler->addOccurrence() that does special handling ...
static StringRef OptionPrefix
static bool RequiresValue(const Option *O)
static int SubNameCompare(const std::pair< const char *, SubCommand * > *LHS, const std::pair< const char *, SubCommand * > *RHS)
static size_t argPlusPrefixesSize(StringRef ArgName, size_t Pad=DefaultPad)
static bool isPrefixedOrGrouping(const Option *O)
static bool shouldPrintOption(StringRef Name, StringRef Description, const Option &O)
static ManagedStatic< SubCommand > AllSubCommands
static Option * HandlePrefixedOrGroupedOption(StringRef &Arg, StringRef &Value, bool &ErrorParsing, const StringMap< Option * > &OptionsMap)
HandlePrefixedOrGroupedOption - The specified argument string (which started with at least one '-') d...
static bool parseDouble(Option &O, StringRef Arg, double &Value)
static bool parseBool(Option &O, StringRef ArgName, StringRef Arg, T &Value)
static const size_t DefaultPad
static StringRef EmptyOption
static bool hasUTF8ByteOrderMark(ArrayRef< char > S)
static ManagedStatic< CommandLineParser > GlobalParser
static void ExpandBasePaths(StringRef BasePath, StringSaver &Saver, const char *&Arg)
static SmallString< 8 > argPrefix(StringRef ArgName, size_t Pad=DefaultPad)
static StringRef ArgHelpPrefix
static bool isWindowsSpecialCharInCommandName(char C)
static Option * getOptionPred(StringRef Name, size_t &Length, bool(*Pred)(const Option *), const StringMap< Option * > &OptionsMap)
static StringRef getValueStr(const Option &O, StringRef DefaultMsg)
static size_t getOptionPrefixesSize()
static bool ProvideOption(Option *Handler, StringRef ArgName, StringRef Value, int argc, const char *const *argv, int &i)
ProvideOption - For Value, this differentiates between an empty value ("") and a null value (StringRe...
static bool isQuote(char C)
static ManagedStatic< CommandLineCommonOptions > CommonOptions
static void initCommonOptions()
static void tokenizeWindowsCommandLineImpl(StringRef Src, StringSaver &Saver, function_ref< void(StringRef)> AddToken, bool AlwaysCopy, function_ref< void()> MarkEOL, bool InitialCommandName)
static bool isWhitespace(char C)
static LLVM_REQUIRE_CONSTANT_INITIALIZATION ManagedStatic< SubCommand > TopLevelSubCommand
static size_t parseBackslash(StringRef Src, size_t I, SmallString< 128 > &Token)
Backslashes are interpreted in a rather complicated way in the Windows-style command line,...
static StringRef ArgPrefixLong
static void sortSubCommands(const SmallPtrSetImpl< SubCommand * > &SubMap, SmallVectorImpl< std::pair< const char *, SubCommand * > > &Subs)
#define PRINT_OPT_DIFF(T)
static bool isWhitespaceOrNull(char C)
static const size_t MaxOptWidth
static Option * LookupNearestOption(StringRef Arg, const StringMap< Option * > &OptionsMap, std::string &NearestString)
LookupNearestOption - Lookup the closest match to the option specified by the specified option on the...
static bool EatsUnboundedNumberOfValues(const Option *O)
static int OptNameCompare(const std::pair< const char *, Option * > *LHS, const std::pair< const char *, Option * > *RHS)
static void sortOpts(StringMap< Option * > &OptMap, SmallVectorImpl< std::pair< const char *, Option * > > &Opts, bool ShowHidden)
static StringRef ArgPrefix
static bool isWindowsSpecialChar(char C)
static bool isGrouping(const Option *O)
#define LLVM_REQUIRE_CONSTANT_INITIALIZATION
LLVM_REQUIRE_CONSTANT_INITIALIZATION - Apply this to globals to ensure that they are constant initial...
static void Help(ArrayRef< StringRef > CPUNames, ArrayRef< SubtargetFeatureKV > FeatTable)
Display help for feature and mcpu choices.
Provides a library for accessing information about this process and other processes on the operating ...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallPtrSet class.
This file defines the SmallString class.
Defines the virtual file system interface vfs::FileSystem.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
ArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
size_t size() const
size - Get the array size.
Allocate memory in an ever growing pool, as if by bump-pointer.
Represents either an error or a value T.
std::error_code getError() const
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
ManagedStatic - This transparently changes the behavior of global statics to be lazily constructed on...
This interface provides simple read-only access to a block of memory, and provides simple methods for...
size_t getBufferSize() const
const char * getBufferEnd() const
const char * getBufferStart() const
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
void assign(StringRef RHS)
Assign from a StringRef.
void append(StringRef RHS)
Append from a StringRef.
StringRef str() const
Explicit conversion to StringRef.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void assign(size_type NumElts, ValueParamT Elt)
iterator erase(const_iterator CI)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
iterator find(StringRef Key)
size_type count(StringRef Key) const
count - Return 1 if the element is in the map, 0 otherwise.
StringRef - Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr bool empty() const
empty - Check if the string is empty.
unsigned edit_distance(StringRef Other, bool AllowReplacements=true, unsigned MaxEditDistance=0) const
Determine the edit distance between this string and another string.
constexpr size_t size() const
size - Get the string size.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
bool consume_front(StringRef Prefix)
Returns true if this StringRef has the given prefix and removes that prefix.
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
static constexpr size_t npos
Saves strings in the provided stable storage and returns a StringRef with a stable character pointer.
BumpPtrAllocator & getAllocator() const
StringRef save(const char *S)
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
LLVM Value Representation.
Contains options that control response file expansion.
bool findConfigFile(StringRef FileName, SmallVectorImpl< char > &FilePath)
Looks for the specified configuration file.
ExpansionContext(BumpPtrAllocator &A, TokenizerCallback T)
Error expandResponseFiles(SmallVectorImpl< const char * > &Argv)
Expands constructs "@file" in the provided array of arguments recursively.
Error readConfigFile(StringRef CfgFile, SmallVectorImpl< const char * > &Argv)
Reads command line options from the given configuration file.
StringRef getDescription() const
StringRef getName() const
SmallPtrSet< SubCommand *, 1 > Subs
int getNumOccurrences() const
enum ValueExpected getValueExpectedFlag() const
void addCategory(OptionCategory &C)
virtual bool addOccurrence(unsigned pos, StringRef ArgName, StringRef Value, bool MultiArg=false)
void setMiscFlag(enum MiscFlags M)
enum FormattingFlags getFormattingFlag() const
virtual void printOptionInfo(size_t GlobalWidth) const =0
enum NumOccurrencesFlag getNumOccurrencesFlag() const
SmallVector< OptionCategory *, 1 > Categories
bool error(const Twine &Message, StringRef ArgName=StringRef(), raw_ostream &Errs=llvm::errs())
void setArgStr(StringRef S)
bool isDefaultOption() const
unsigned getMiscFlags() const
virtual void setDefault()=0
static void printEnumValHelpStr(StringRef HelpStr, size_t Indent, size_t FirstLineIndentedBy)
unsigned getNumAdditionalVals() const
void removeArgument()
Unregisters this option from the CommandLine system.
static void printHelpStr(StringRef HelpStr, size_t Indent, size_t FirstLineIndentedBy)
StringRef getName() const
SmallVector< Option *, 4 > SinkOpts
static SubCommand & getTopLevel()
void unregisterSubCommand()
static SubCommand & getAll()
void registerSubCommand()
SmallVector< Option *, 4 > PositionalOpts
StringMap< Option * > OptionsMap
StringRef getDescription() const
void printOptionInfo(const Option &O, size_t GlobalWidth) const
virtual StringRef getValueName() const
void printOptionNoValue(const Option &O, size_t GlobalWidth) const
size_t getOptionWidth(const Option &O) const
void printOptionName(const Option &O, size_t GlobalWidth) const
virtual size_t getOptionWidth(const Option &O) const
virtual StringRef getDescription(unsigned N) const =0
virtual const GenericOptionValue & getOptionValue(unsigned N) const =0
virtual unsigned getNumOptions() const =0
virtual StringRef getOption(unsigned N) const =0
void printOptionDiff(const Option &O, const AnyOptionValue &V, const AnyOptionValue &Default, size_t GlobalWidth) const
void printGenericOptionDiff(const Option &O, const GenericOptionValue &V, const GenericOptionValue &Default, size_t GlobalWidth) const
virtual void printOptionInfo(const Option &O, size_t GlobalWidth) const
unsigned findOption(StringRef Name)
bool parse(Option &O, StringRef ArgName, StringRef Arg, DataType &V)
An efficient, type-erasing, non-owning reference to a callable.
A range adaptor for a pair of iterators.
This class implements an extremely fast bulk output stream that can only output to a stream.
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
static std::optional< std::string > GetEnv(StringRef name)
virtual llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const =0
Get the working directory of this file system.
virtual std::error_code makeAbsolute(SmallVectorImpl< char > &Path) const
Make Path an absolute path.
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getBufferForFile(const Twine &Name, int64_t FileSize=-1, bool RequiresNullTerminator=true, bool IsVolatile=false, bool IsText=true)
This is a convenience method that opens a file, gets its content and then closes the file.
virtual llvm::ErrorOr< Status > status(const Twine &Path)=0
Get the status of the entry at Path, if one exists.
The result of a status operation.
bool equivalent(const Status &Other) const
void LLVMParseCommandLineOptions(int argc, const char *const *argv, const char *Overview)
This function parses the given arguments using the LLVM command line parser.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
@ SC
CHAIN = SC CHAIN, Imm128 - System call.
constexpr size_t NameSize
std::function< void(raw_ostream &)> VersionPrinterTy
void(*)(StringRef Source, StringSaver &Saver, SmallVectorImpl< const char * > &NewArgv, bool MarkEOLs) TokenizerCallback
String tokenization function type.
void PrintVersionMessage()
Utility function for printing version number.
bool ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer, SmallVectorImpl< const char * > &Argv)
A convenience helper which supports the typical use case of expansion function call.
bool expandResponseFiles(int Argc, const char *const *Argv, const char *EnvVar, SmallVectorImpl< const char * > &NewArgv)
A convenience helper which concatenates the options specified by the environment variable EnvVar and ...
void TokenizeWindowsCommandLine(StringRef Source, StringSaver &Saver, SmallVectorImpl< const char * > &NewArgv, bool MarkEOLs=false)
Tokenizes a string of Windows command line arguments, which may contain quotes and escaped quotes.
OptionCategory & getGeneralCategory()
void ResetAllOptionOccurrences()
Reset all command line options to a state that looks as if they have never appeared on the command li...
void SetVersionPrinter(VersionPrinterTy func)
===------------------------------------------------------------------—===// Override the default (LLV...
void tokenizeConfigFile(StringRef Source, StringSaver &Saver, SmallVectorImpl< const char * > &NewArgv, bool MarkEOLs=false)
Tokenizes content of configuration file.
StringMap< Option * > & getRegisteredOptions(SubCommand &Sub=SubCommand::getTopLevel())
Use this to get a StringMap to all registered named options (e.g.
void ResetCommandLineParser()
Reset the command line parser back to its initial state.
bool ParseCommandLineOptions(int argc, const char *const *argv, StringRef Overview="", raw_ostream *Errs=nullptr, const char *EnvVar=nullptr, bool LongOptionsUseDoubleDash=false)
iterator_range< typename SmallPtrSet< SubCommand *, 4 >::iterator > getRegisteredSubcommands()
Use this to get all registered SubCommands from the provided parser.
void AddLiteralOption(Option &O, StringRef Name)
Adds a new option for parsing and provides the option it refers to.
void TokenizeWindowsCommandLineNoCopy(StringRef Source, StringSaver &Saver, SmallVectorImpl< StringRef > &NewArgv)
Tokenizes a Windows command line while attempting to avoid copies.
void printBuildConfig(raw_ostream &OS)
Prints the compiler build configuration.
bool ProvidePositionalOption(Option *Handler, StringRef Arg, int i)
Parses Arg into the option handler Handler.
initializer< Ty > init(const Ty &Val)
ArrayRef< StringRef > getCompilerBuildConfig()
An array of optional enabled settings in the LLVM build configuration, which may be of interest to co...
LocationClass< Ty > location(Ty &L)
void HideUnrelatedOptions(cl::OptionCategory &Category, SubCommand &Sub=SubCommand::getTopLevel())
Mark all options not part of this category as cl::ReallyHidden.
void AddExtraVersionPrinter(VersionPrinterTy func)
===------------------------------------------------------------------—===// Add an extra printer to u...
void PrintHelpMessage(bool Hidden=false, bool Categorized=false)
This function just prints the help message, exactly the same way as if the -help or -help-hidden opti...
void TokenizeWindowsCommandLineFull(StringRef Source, StringSaver &Saver, SmallVectorImpl< const char * > &NewArgv, bool MarkEOLs=false)
Tokenizes a Windows full command line, including command name at the start.
void TokenizeGNUCommandLine(StringRef Source, StringSaver &Saver, SmallVectorImpl< const char * > &NewArgv, bool MarkEOLs=false)
Tokenizes a command line that can contain escapes and quotes.
StringRef parent_path(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get parent path.
bool has_parent_path(const Twine &path, Style style=Style::native)
Has parent path?
bool is_relative(const Twine &path, Style style=Style::native)
Is path relative?
StringRef filename(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get filename.
bool is_absolute(const Twine &path, Style style=Style::native)
Is path absolute?
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
void initWithColorOptions()
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
raw_fd_ostream & outs()
This returns a reference to a raw_fd_ostream for standard output.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
void interleaveComma(const Container &c, StreamT &os, UnaryFunctor each_fn)
bool hasUTF16ByteOrderMark(ArrayRef< char > SrcBytes)
Returns true if a blob of text starts with a UTF-16 big or little endian byte order mark.
void initDebugCounterOptions()
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr)
@ no_such_file_or_directory
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
bool convertUTF16ToUTF8String(ArrayRef< char > SrcBytes, std::string &Out)
Converts a stream of raw bytes assumed to be UTF16 into a UTF8 std::string.
void initSignalsOptions()
void initTypeSizeOptions()
void initStatisticOptions()
raw_ostream & nulls()
This returns a reference to a raw_ostream which simply discards output.
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
void initRandomSeedOptions()
void initGraphWriterOptions()
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
const char * toString(DWARFSectionKind Kind)
void array_pod_sort(IteratorTy Start, IteratorTy End)
array_pod_sort - This sorts an array with the specified start and end extent.
@ Default
The result values are uniform if and only if all operands are uniform.