1 //===- OptTable.cpp - Option Table Implementation -------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/Option/OptTable.h"
10 #include "llvm/ADT/STLExtras.h"
11 #include "llvm/ADT/StringRef.h"
12 #include "llvm/Option/Arg.h"
13 #include "llvm/Option/ArgList.h"
14 #include "llvm/Option/OptSpecifier.h"
15 #include "llvm/Option/Option.h"
16 #include "llvm/Support/CommandLine.h" // for expandResponseFiles
17 #include "llvm/Support/Compiler.h"
18 #include "llvm/Support/ErrorHandling.h"
19 #include "llvm/Support/raw_ostream.h"
31 using namespace llvm::opt
;
36 // Ordering on Info. The ordering is *almost* case-insensitive lexicographic,
37 // with an exception. '\0' comes at the end of the alphabet instead of the
38 // beginning (thus options precede any other options which prefix them).
39 static int StrCmpOptionNameIgnoreCase(StringRef A
, StringRef B
) {
40 size_t MinSize
= std::min(A
.size(), B
.size());
41 if (int Res
= A
.substr(0, MinSize
).compare_insensitive(B
.substr(0, MinSize
)))
44 if (A
.size() == B
.size())
47 return (A
.size() == MinSize
) ? 1 /* A is a prefix of B. */
48 : -1 /* B is a prefix of A */;
52 static int StrCmpOptionName(StringRef A
, StringRef B
) {
53 if (int N
= StrCmpOptionNameIgnoreCase(A
, B
))
58 static inline bool operator<(const OptTable::Info
&A
, const OptTable::Info
&B
) {
62 if (int N
= StrCmpOptionName(A
.Name
, B
.Name
))
65 for (size_t I
= 0, K
= std::min(A
.Prefixes
.size(), B
.Prefixes
.size()); I
!= K
;
67 if (int N
= StrCmpOptionName(A
.Prefixes
[I
], B
.Prefixes
[I
]))
70 // Names are the same, check that classes are in order; exactly one
71 // should be joined, and it should succeed the other.
72 assert(((A
.Kind
== Option::JoinedClass
) ^ (B
.Kind
== Option::JoinedClass
)) &&
73 "Unexpected classes for options with same name.");
74 return B
.Kind
== Option::JoinedClass
;
78 // Support lower_bound between info and an option name.
79 static inline bool operator<(const OptTable::Info
&I
, StringRef Name
) {
80 return StrCmpOptionNameIgnoreCase(I
.Name
, Name
) < 0;
83 } // end namespace opt
84 } // end namespace llvm
86 OptSpecifier::OptSpecifier(const Option
*Opt
) : ID(Opt
->getID()) {}
88 OptTable::OptTable(ArrayRef
<Info
> OptionInfos
, bool IgnoreCase
)
89 : OptionInfos(OptionInfos
), IgnoreCase(IgnoreCase
) {
90 // Explicitly zero initialize the error to work around a bug in array
91 // value-initialization on MinGW with gcc 4.3.5.
93 // Find start of normal options.
94 for (unsigned i
= 0, e
= getNumOptions(); i
!= e
; ++i
) {
95 unsigned Kind
= getInfo(i
+ 1).Kind
;
96 if (Kind
== Option::InputClass
) {
97 assert(!InputOptionID
&& "Cannot have multiple input options!");
98 InputOptionID
= getInfo(i
+ 1).ID
;
99 } else if (Kind
== Option::UnknownClass
) {
100 assert(!UnknownOptionID
&& "Cannot have multiple unknown options!");
101 UnknownOptionID
= getInfo(i
+ 1).ID
;
102 } else if (Kind
!= Option::GroupClass
) {
103 FirstSearchableIndex
= i
;
107 assert(FirstSearchableIndex
!= 0 && "No searchable options?");
110 // Check that everything after the first searchable option is a
111 // regular option class.
112 for (unsigned i
= FirstSearchableIndex
, e
= getNumOptions(); i
!= e
; ++i
) {
113 Option::OptionClass Kind
= (Option::OptionClass
) getInfo(i
+ 1).Kind
;
114 assert((Kind
!= Option::InputClass
&& Kind
!= Option::UnknownClass
&&
115 Kind
!= Option::GroupClass
) &&
116 "Special options should be defined first!");
119 // Check that options are in order.
120 for (unsigned i
= FirstSearchableIndex
+ 1, e
= getNumOptions(); i
!= e
; ++i
){
121 if (!(getInfo(i
) < getInfo(i
+ 1))) {
123 getOption(i
+ 1).dump();
124 llvm_unreachable("Options are not in order!");
130 void OptTable::buildPrefixChars() {
131 assert(PrefixChars
.empty() && "rebuilding a non-empty prefix char");
133 // Build prefix chars.
134 for (const StringLiteral
&Prefix
: getPrefixesUnion()) {
135 for (char C
: Prefix
)
136 if (!is_contained(PrefixChars
, C
))
137 PrefixChars
.push_back(C
);
141 OptTable::~OptTable() = default;
143 const Option
OptTable::getOption(OptSpecifier Opt
) const {
144 unsigned id
= Opt
.getID();
146 return Option(nullptr, nullptr);
147 assert((unsigned) (id
- 1) < getNumOptions() && "Invalid ID.");
148 return Option(&getInfo(id
), this);
151 static bool isInput(const ArrayRef
<StringLiteral
> &Prefixes
, StringRef Arg
) {
154 for (const StringRef
&Prefix
: Prefixes
)
155 if (Arg
.startswith(Prefix
))
160 /// \returns Matched size. 0 means no match.
161 static unsigned matchOption(const OptTable::Info
*I
, StringRef Str
,
163 for (auto Prefix
: I
->Prefixes
) {
164 if (Str
.startswith(Prefix
)) {
165 StringRef Rest
= Str
.substr(Prefix
.size());
166 bool Matched
= IgnoreCase
? Rest
.starts_with_insensitive(I
->Name
)
167 : Rest
.startswith(I
->Name
);
169 return Prefix
.size() + StringRef(I
->Name
).size();
175 // Returns true if one of the Prefixes + In.Names matches Option
176 static bool optionMatches(const OptTable::Info
&In
, StringRef Option
) {
177 for (auto Prefix
: In
.Prefixes
)
178 if (Option
.endswith(In
.Name
))
179 if (Option
.slice(0, Option
.size() - In
.Name
.size()) == Prefix
)
184 // This function is for flag value completion.
185 // Eg. When "-stdlib=" and "l" was passed to this function, it will return
186 // appropiriate values for stdlib, which starts with l.
187 std::vector
<std::string
>
188 OptTable::suggestValueCompletions(StringRef Option
, StringRef Arg
) const {
189 // Search all options and return possible values.
190 for (size_t I
= FirstSearchableIndex
, E
= OptionInfos
.size(); I
< E
; I
++) {
191 const Info
&In
= OptionInfos
[I
];
192 if (!In
.Values
|| !optionMatches(In
, Option
))
195 SmallVector
<StringRef
, 8> Candidates
;
196 StringRef(In
.Values
).split(Candidates
, ",", -1, false);
198 std::vector
<std::string
> Result
;
199 for (StringRef Val
: Candidates
)
200 if (Val
.startswith(Arg
) && Arg
.compare(Val
))
201 Result
.push_back(std::string(Val
));
207 std::vector
<std::string
>
208 OptTable::findByPrefix(StringRef Cur
, unsigned int DisableFlags
) const {
209 std::vector
<std::string
> Ret
;
210 for (size_t I
= FirstSearchableIndex
, E
= OptionInfos
.size(); I
< E
; I
++) {
211 const Info
&In
= OptionInfos
[I
];
212 if (In
.Prefixes
.empty() || (!In
.HelpText
&& !In
.GroupID
))
214 if (In
.Flags
& DisableFlags
)
217 for (auto Prefix
: In
.Prefixes
) {
218 std::string S
= (Prefix
+ In
.Name
+ "\t").str();
221 if (StringRef(S
).startswith(Cur
) && S
!= std::string(Cur
) + "\t")
228 unsigned OptTable::findNearest(StringRef Option
, std::string
&NearestString
,
229 unsigned FlagsToInclude
, unsigned FlagsToExclude
,
230 unsigned MinimumLength
,
231 unsigned MaximumDistance
) const {
232 assert(!Option
.empty());
234 // Consider each [option prefix + option name] pair as a candidate, finding
235 // the closest match.
236 unsigned BestDistance
=
237 MaximumDistance
== UINT_MAX
? UINT_MAX
: MaximumDistance
+ 1;
238 SmallString
<16> Candidate
;
239 SmallString
<16> NormalizedName
;
241 for (const Info
&CandidateInfo
:
242 ArrayRef
<Info
>(OptionInfos
).drop_front(FirstSearchableIndex
)) {
243 StringRef CandidateName
= CandidateInfo
.Name
;
245 // We can eliminate some option prefix/name pairs as candidates right away:
246 // * Ignore option candidates with empty names, such as "--", or names
247 // that do not meet the minimum length.
248 if (CandidateName
.size() < MinimumLength
)
251 // * If FlagsToInclude were specified, ignore options that don't include
253 if (FlagsToInclude
&& !(CandidateInfo
.Flags
& FlagsToInclude
))
255 // * Ignore options that contain the FlagsToExclude.
256 if (CandidateInfo
.Flags
& FlagsToExclude
)
259 // * Ignore positional argument option candidates (which do not
261 if (CandidateInfo
.Prefixes
.empty())
264 // Now check if the candidate ends with a character commonly used when
265 // delimiting an option from its value, such as '=' or ':'. If it does,
266 // attempt to split the given option based on that delimiter.
267 char Last
= CandidateName
.back();
268 bool CandidateHasDelimiter
= Last
== '=' || Last
== ':';
270 if (CandidateHasDelimiter
) {
271 std::tie(NormalizedName
, RHS
) = Option
.split(Last
);
272 if (Option
.find(Last
) == NormalizedName
.size())
273 NormalizedName
+= Last
;
275 NormalizedName
= Option
;
277 // Consider each possible prefix for each candidate to find the most
278 // appropriate one. For example, if a user asks for "--helm", suggest
279 // "--help" over "-help".
280 for (auto CandidatePrefix
: CandidateInfo
.Prefixes
) {
281 // If Candidate and NormalizedName have more than 'BestDistance'
282 // characters of difference, no need to compute the edit distance, it's
283 // going to be greater than BestDistance. Don't bother computing Candidate
285 size_t CandidateSize
= CandidatePrefix
.size() + CandidateName
.size(),
286 NormalizedSize
= NormalizedName
.size();
287 size_t AbsDiff
= CandidateSize
> NormalizedSize
288 ? CandidateSize
- NormalizedSize
289 : NormalizedSize
- CandidateSize
;
290 if (AbsDiff
> BestDistance
) {
293 Candidate
= CandidatePrefix
;
294 Candidate
+= CandidateName
;
295 unsigned Distance
= StringRef(Candidate
).edit_distance(
296 NormalizedName
, /*AllowReplacements=*/true,
297 /*MaxEditDistance=*/BestDistance
);
298 if (RHS
.empty() && CandidateHasDelimiter
) {
299 // The Candidate ends with a = or : delimiter, but the option passed in
300 // didn't contain the delimiter (or doesn't have anything after it).
301 // In that case, penalize the correction: `-nodefaultlibs` is more
302 // likely to be a spello for `-nodefaultlib` than `-nodefaultlib:` even
303 // though both have an unmodified editing distance of 1, since the
304 // latter would need an argument.
307 if (Distance
< BestDistance
) {
308 BestDistance
= Distance
;
309 NearestString
= (Candidate
+ RHS
).str();
316 // Parse a single argument, return the new argument, and update Index. If
317 // GroupedShortOptions is true, -a matches "-abc" and the argument in Args will
318 // be updated to "-bc". This overload does not support
319 // FlagsToInclude/FlagsToExclude or case insensitive options.
320 std::unique_ptr
<Arg
> OptTable::parseOneArgGrouped(InputArgList
&Args
,
321 unsigned &Index
) const {
322 // Anything that doesn't start with PrefixesUnion is an input, as is '-'
324 const char *CStr
= Args
.getArgString(Index
);
326 if (isInput(getPrefixesUnion(), Str
))
327 return std::make_unique
<Arg
>(getOption(InputOptionID
), Str
, Index
++, CStr
);
329 const Info
*End
= OptionInfos
.data() + OptionInfos
.size();
330 StringRef Name
= Str
.ltrim(PrefixChars
);
332 std::lower_bound(OptionInfos
.data() + FirstSearchableIndex
, End
, Name
);
333 const Info
*Fallback
= nullptr;
334 unsigned Prev
= Index
;
336 // Search for the option which matches Str.
337 for (; Start
!= End
; ++Start
) {
338 unsigned ArgSize
= matchOption(Start
, Str
, IgnoreCase
);
342 Option
Opt(Start
, this);
343 if (std::unique_ptr
<Arg
> A
=
344 Opt
.accept(Args
, StringRef(Args
.getArgString(Index
), ArgSize
),
345 /*GroupedShortOption=*/false, Index
))
348 // If Opt is a Flag of length 2 (e.g. "-a"), we know it is a prefix of
349 // the current argument (e.g. "-abc"). Match it as a fallback if no longer
350 // option (e.g. "-ab") exists.
351 if (ArgSize
== 2 && Opt
.getKind() == Option::FlagClass
)
354 // Otherwise, see if the argument is missing.
359 Option
Opt(Fallback
, this);
360 // Check that the last option isn't a flag wrongly given an argument.
362 return std::make_unique
<Arg
>(getOption(UnknownOptionID
), Str
, Index
++,
365 if (std::unique_ptr
<Arg
> A
= Opt
.accept(
366 Args
, Str
.substr(0, 2), /*GroupedShortOption=*/true, Index
)) {
367 Args
.replaceArgString(Index
, Twine('-') + Str
.substr(2));
372 // In the case of an incorrect short option extract the character and move to
375 CStr
= Args
.MakeArgString(Str
.substr(0, 2));
376 Args
.replaceArgString(Index
, Twine('-') + Str
.substr(2));
377 return std::make_unique
<Arg
>(getOption(UnknownOptionID
), CStr
, Index
, CStr
);
380 return std::make_unique
<Arg
>(getOption(UnknownOptionID
), Str
, Index
++, CStr
);
383 std::unique_ptr
<Arg
> OptTable::ParseOneArg(const ArgList
&Args
, unsigned &Index
,
384 unsigned FlagsToInclude
,
385 unsigned FlagsToExclude
) const {
386 unsigned Prev
= Index
;
387 StringRef Str
= Args
.getArgString(Index
);
389 // Anything that doesn't start with PrefixesUnion is an input, as is '-'
391 if (isInput(getPrefixesUnion(), Str
))
392 return std::make_unique
<Arg
>(getOption(InputOptionID
), Str
, Index
++,
395 const Info
*Start
= OptionInfos
.data() + FirstSearchableIndex
;
396 const Info
*End
= OptionInfos
.data() + OptionInfos
.size();
397 StringRef Name
= Str
.ltrim(PrefixChars
);
399 // Search for the first next option which could be a prefix.
400 Start
= std::lower_bound(Start
, End
, Name
);
402 // Options are stored in sorted order, with '\0' at the end of the
403 // alphabet. Since the only options which can accept a string must
404 // prefix it, we iteratively search for the next option which could
407 // FIXME: This is searching much more than necessary, but I am
408 // blanking on the simplest way to make it fast. We can solve this
409 // problem when we move to TableGen.
410 for (; Start
!= End
; ++Start
) {
411 unsigned ArgSize
= 0;
412 // Scan for first option which is a proper prefix.
413 for (; Start
!= End
; ++Start
)
414 if ((ArgSize
= matchOption(Start
, Str
, IgnoreCase
)))
419 Option
Opt(Start
, this);
421 if (FlagsToInclude
&& !Opt
.hasFlag(FlagsToInclude
))
423 if (Opt
.hasFlag(FlagsToExclude
))
426 // See if this option matches.
427 if (std::unique_ptr
<Arg
> A
=
428 Opt
.accept(Args
, StringRef(Args
.getArgString(Index
), ArgSize
),
429 /*GroupedShortOption=*/false, Index
))
432 // Otherwise, see if this argument was missing values.
437 // If we failed to find an option and this arg started with /, then it's
438 // probably an input path.
440 return std::make_unique
<Arg
>(getOption(InputOptionID
), Str
, Index
++,
443 return std::make_unique
<Arg
>(getOption(UnknownOptionID
), Str
, Index
++,
447 InputArgList
OptTable::ParseArgs(ArrayRef
<const char *> ArgArr
,
448 unsigned &MissingArgIndex
,
449 unsigned &MissingArgCount
,
450 unsigned FlagsToInclude
,
451 unsigned FlagsToExclude
) const {
452 InputArgList
Args(ArgArr
.begin(), ArgArr
.end());
454 // FIXME: Handle '@' args (or at least error on them).
456 MissingArgIndex
= MissingArgCount
= 0;
457 unsigned Index
= 0, End
= ArgArr
.size();
458 while (Index
< End
) {
459 // Ingore nullptrs, they are response file's EOL markers
460 if (Args
.getArgString(Index
) == nullptr) {
464 // Ignore empty arguments (other things may still take them as arguments).
465 StringRef Str
= Args
.getArgString(Index
);
471 // In DashDashParsing mode, the first "--" stops option scanning and treats
472 // all subsequent arguments as positional.
473 if (DashDashParsing
&& Str
== "--") {
474 while (++Index
< End
) {
475 Args
.append(new Arg(getOption(InputOptionID
), Str
, Index
,
476 Args
.getArgString(Index
)));
481 unsigned Prev
= Index
;
482 std::unique_ptr
<Arg
> A
= GroupedShortOptions
483 ? parseOneArgGrouped(Args
, Index
)
484 : ParseOneArg(Args
, Index
, FlagsToInclude
, FlagsToExclude
);
485 assert((Index
> Prev
|| GroupedShortOptions
) &&
486 "Parser failed to consume argument.");
488 // Check for missing argument error.
490 assert(Index
>= End
&& "Unexpected parser error.");
491 assert(Index
- Prev
- 1 && "No missing arguments!");
492 MissingArgIndex
= Prev
;
493 MissingArgCount
= Index
- Prev
- 1;
497 Args
.append(A
.release());
503 InputArgList
OptTable::parseArgs(int Argc
, char *const *Argv
,
504 OptSpecifier Unknown
, StringSaver
&Saver
,
505 function_ref
<void(StringRef
)> ErrorFn
) const {
506 SmallVector
<const char *, 0> NewArgv
;
507 // The environment variable specifies initial options which can be overridden
508 // by commnad line options.
509 cl::expandResponseFiles(Argc
, Argv
, EnvVar
, Saver
, NewArgv
);
512 opt::InputArgList Args
= ParseArgs(ArrayRef(NewArgv
), MAI
, MAC
);
514 ErrorFn((Twine(Args
.getArgString(MAI
)) + ": missing argument").str());
516 // For each unknwon option, call ErrorFn with a formatted error message. The
517 // message includes a suggested alternative option spelling if available.
519 for (const opt::Arg
*A
: Args
.filtered(Unknown
)) {
520 std::string Spelling
= A
->getAsString(Args
);
521 if (findNearest(Spelling
, Nearest
) > 1)
522 ErrorFn("unknown argument '" + Spelling
+ "'");
524 ErrorFn("unknown argument '" + Spelling
+ "', did you mean '" + Nearest
+
530 static std::string
getOptionHelpName(const OptTable
&Opts
, OptSpecifier Id
) {
531 const Option O
= Opts
.getOption(Id
);
532 std::string Name
= O
.getPrefixedName();
534 // Add metavar, if used.
535 switch (O
.getKind()) {
536 case Option::GroupClass
: case Option::InputClass
: case Option::UnknownClass
:
537 llvm_unreachable("Invalid option with help text.");
539 case Option::MultiArgClass
:
540 if (const char *MetaVarName
= Opts
.getOptionMetaVar(Id
)) {
541 // For MultiArgs, metavar is full list of all argument names.
546 // For MultiArgs<N>, if metavar not supplied, print <value> N times.
547 for (unsigned i
=0, e
=O
.getNumArgs(); i
< e
; ++i
) {
553 case Option::FlagClass
:
556 case Option::ValuesClass
:
559 case Option::SeparateClass
: case Option::JoinedOrSeparateClass
:
560 case Option::RemainingArgsClass
: case Option::RemainingArgsJoinedClass
:
563 case Option::JoinedClass
: case Option::CommaJoinedClass
:
564 case Option::JoinedAndSeparateClass
:
565 if (const char *MetaVarName
= Opts
.getOptionMetaVar(Id
))
582 static void PrintHelpOptionList(raw_ostream
&OS
, StringRef Title
,
583 std::vector
<OptionInfo
> &OptionHelp
) {
584 OS
<< Title
<< ":\n";
586 // Find the maximum option length.
587 unsigned OptionFieldWidth
= 0;
588 for (const OptionInfo
&Opt
: OptionHelp
) {
589 // Limit the amount of padding we are willing to give up for alignment.
590 unsigned Length
= Opt
.Name
.size();
592 OptionFieldWidth
= std::max(OptionFieldWidth
, Length
);
595 const unsigned InitialPad
= 2;
596 for (const OptionInfo
&Opt
: OptionHelp
) {
597 const std::string
&Option
= Opt
.Name
;
598 int Pad
= OptionFieldWidth
- int(Option
.size());
599 OS
.indent(InitialPad
) << Option
;
601 // Break on long option names.
604 Pad
= OptionFieldWidth
+ InitialPad
;
606 OS
.indent(Pad
+ 1) << Opt
.HelpText
<< '\n';
610 static const char *getOptionHelpGroup(const OptTable
&Opts
, OptSpecifier Id
) {
611 unsigned GroupID
= Opts
.getOptionGroupID(Id
);
613 // If not in a group, return the default help group.
617 // Abuse the help text of the option groups to store the "help group"
620 // FIXME: Split out option groups.
621 if (const char *GroupHelp
= Opts
.getOptionHelpText(GroupID
))
624 // Otherwise keep looking.
625 return getOptionHelpGroup(Opts
, GroupID
);
628 void OptTable::printHelp(raw_ostream
&OS
, const char *Usage
, const char *Title
,
629 bool ShowHidden
, bool ShowAllAliases
) const {
630 printHelp(OS
, Usage
, Title
, /*Include*/ 0, /*Exclude*/
631 (ShowHidden
? 0 : HelpHidden
), ShowAllAliases
);
634 void OptTable::printHelp(raw_ostream
&OS
, const char *Usage
, const char *Title
,
635 unsigned FlagsToInclude
, unsigned FlagsToExclude
,
636 bool ShowAllAliases
) const {
637 OS
<< "OVERVIEW: " << Title
<< "\n\n";
638 OS
<< "USAGE: " << Usage
<< "\n\n";
640 // Render help text into a map of group-name to a list of (option, help)
642 std::map
<std::string
, std::vector
<OptionInfo
>> GroupedOptionHelp
;
644 for (unsigned Id
= 1, e
= getNumOptions() + 1; Id
!= e
; ++Id
) {
645 // FIXME: Split out option groups.
646 if (getOptionKind(Id
) == Option::GroupClass
)
649 unsigned Flags
= getInfo(Id
).Flags
;
650 if (FlagsToInclude
&& !(Flags
& FlagsToInclude
))
652 if (Flags
& FlagsToExclude
)
655 // If an alias doesn't have a help text, show a help text for the aliased
657 const char *HelpText
= getOptionHelpText(Id
);
658 if (!HelpText
&& ShowAllAliases
) {
659 const Option Alias
= getOption(Id
).getAlias();
661 HelpText
= getOptionHelpText(Alias
.getID());
664 if (HelpText
&& (strlen(HelpText
) != 0)) {
665 const char *HelpGroup
= getOptionHelpGroup(*this, Id
);
666 const std::string
&OptName
= getOptionHelpName(*this, Id
);
667 GroupedOptionHelp
[HelpGroup
].push_back({OptName
, HelpText
});
671 for (auto& OptionGroup
: GroupedOptionHelp
) {
672 if (OptionGroup
.first
!= GroupedOptionHelp
.begin()->first
)
674 PrintHelpOptionList(OS
, OptionGroup
.first
, OptionGroup
.second
);
680 GenericOptTable::GenericOptTable(ArrayRef
<Info
> OptionInfos
, bool IgnoreCase
)
681 : OptTable(OptionInfos
, IgnoreCase
) {
683 std::set
<StringLiteral
> TmpPrefixesUnion
;
684 for (auto const &Info
: OptionInfos
.drop_front(FirstSearchableIndex
))
685 TmpPrefixesUnion
.insert(Info
.Prefixes
.begin(), Info
.Prefixes
.end());
686 PrefixesUnionBuffer
.append(TmpPrefixesUnion
.begin(), TmpPrefixesUnion
.end());