clang 20.0.0git
Multilib.cpp
Go to the documentation of this file.
1//===- Multilib.cpp - Multilib Implementation -----------------------------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8
10#include "clang/Basic/LLVM.h"
11#include "clang/Driver/Driver.h"
12#include "llvm/ADT/DenseSet.h"
13#include "llvm/ADT/SmallSet.h"
14#include "llvm/ADT/StringRef.h"
15#include "llvm/Support/Compiler.h"
16#include "llvm/Support/ErrorHandling.h"
17#include "llvm/Support/Regex.h"
18#include "llvm/Support/VersionTuple.h"
19#include "llvm/Support/YAMLParser.h"
20#include "llvm/Support/YAMLTraits.h"
21#include "llvm/Support/raw_ostream.h"
22#include <algorithm>
23#include <cassert>
24#include <string>
25
26using namespace clang;
27using namespace driver;
28using namespace llvm::sys;
29
30Multilib::Multilib(StringRef GCCSuffix, StringRef OSSuffix,
31 StringRef IncludeSuffix, const flags_list &Flags,
32 StringRef ExclusiveGroup, std::optional<StringRef> Error)
33 : GCCSuffix(GCCSuffix), OSSuffix(OSSuffix), IncludeSuffix(IncludeSuffix),
34 Flags(Flags), ExclusiveGroup(ExclusiveGroup), Error(Error) {
35 assert(GCCSuffix.empty() ||
36 (StringRef(GCCSuffix).front() == '/' && GCCSuffix.size() > 1));
37 assert(OSSuffix.empty() ||
38 (StringRef(OSSuffix).front() == '/' && OSSuffix.size() > 1));
39 assert(IncludeSuffix.empty() ||
40 (StringRef(IncludeSuffix).front() == '/' && IncludeSuffix.size() > 1));
41}
42
43LLVM_DUMP_METHOD void Multilib::dump() const {
44 print(llvm::errs());
45}
46
47void Multilib::print(raw_ostream &OS) const {
48 if (GCCSuffix.empty())
49 OS << ".";
50 else {
51 OS << StringRef(GCCSuffix).drop_front();
52 }
53 OS << ";";
54 for (StringRef Flag : Flags) {
55 if (Flag.front() == '-')
56 OS << "@" << Flag.substr(1);
57 }
58}
59
61 // Check whether the flags sets match
62 // allowing for the match to be order invariant
63 llvm::StringSet<> MyFlags;
64 for (const auto &Flag : Flags)
65 MyFlags.insert(Flag);
66
67 for (const auto &Flag : Other.Flags)
68 if (!MyFlags.contains(Flag))
69 return false;
70
71 if (osSuffix() != Other.osSuffix())
72 return false;
73
74 if (gccSuffix() != Other.gccSuffix())
75 return false;
76
77 if (includeSuffix() != Other.includeSuffix())
78 return false;
79
80 return true;
81}
82
83raw_ostream &clang::driver::operator<<(raw_ostream &OS, const Multilib &M) {
84 M.print(OS);
85 return OS;
86}
87
89 llvm::erase_if(Multilibs, F);
90 return *this;
91}
92
93void MultilibSet::push_back(const Multilib &M) { Multilibs.push_back(M); }
94
96 const Driver &D, const SmallVector<StringRef> &UnclaimedCustomFlagValues,
97 const SmallVector<custom_flag::Declaration> &CustomFlagDecls) {
98 struct EditDistanceInfo {
99 StringRef FlagValue;
100 unsigned EditDistance;
101 };
102 const unsigned MaxEditDistance = 5;
103
104 for (StringRef Unclaimed : UnclaimedCustomFlagValues) {
105 std::optional<EditDistanceInfo> BestCandidate;
106 for (const auto &Decl : CustomFlagDecls) {
107 for (const auto &Value : Decl.ValueList) {
108 const std::string &FlagValueName = Value.Name;
109 unsigned EditDistance =
110 Unclaimed.edit_distance(FlagValueName, /*AllowReplacements=*/true,
111 /*MaxEditDistance=*/MaxEditDistance);
112 if (!BestCandidate || (EditDistance <= MaxEditDistance &&
113 EditDistance < BestCandidate->EditDistance)) {
114 BestCandidate = {FlagValueName, EditDistance};
115 }
116 }
117 }
118 if (!BestCandidate)
119 D.Diag(clang::diag::err_drv_unsupported_opt)
120 << (custom_flag::Prefix + Unclaimed).str();
121 else
122 D.Diag(clang::diag::err_drv_unsupported_opt_with_suggestion)
123 << (custom_flag::Prefix + Unclaimed).str()
124 << (custom_flag::Prefix + BestCandidate->FlagValue).str();
125 }
126}
127
129// Map implemented using linear searches as the expected size is too small for
130// the overhead of a search tree or a hash table.
133
134public:
135 template <typename It>
136 ValueNameToDetailMap(It FlagDeclsBegin, It FlagDeclsEnd) {
137 for (auto DeclIt = FlagDeclsBegin; DeclIt != FlagDeclsEnd; ++DeclIt) {
138 const Declaration &Decl = *DeclIt;
139 for (const auto &Value : Decl.ValueList)
140 Mapping.emplace_back(Value.Name, &Value);
141 }
142 }
143
144 const ValueDetail *get(StringRef Key) const {
145 auto Iter = llvm::find_if(
146 Mapping, [&](const auto &Pair) { return Pair.first == Key; });
147 return Iter != Mapping.end() ? Iter->second : nullptr;
148 }
149};
150} // namespace clang::driver::custom_flag
151
152std::pair<Multilib::flags_list, SmallVector<StringRef>>
154 const Multilib::flags_list &Flags) const {
156 SmallVector<StringRef> MacroDefines;
157
158 // Custom flag values detected in the flags list
159 SmallVector<const custom_flag::ValueDetail *> ClaimedCustomFlagValues;
160
161 // Arguments to -fmultilib-flag=<arg> that don't correspond to any valid
162 // custom flag value. An error will be printed out for each of these.
163 SmallVector<StringRef> UnclaimedCustomFlagValueStrs;
164
165 const auto ValueNameToValueDetail = custom_flag::ValueNameToDetailMap(
166 CustomFlagDecls.begin(), CustomFlagDecls.end());
167
168 for (StringRef Flag : Flags) {
169 if (!Flag.starts_with(custom_flag::Prefix)) {
170 Result.push_back(Flag.str());
171 continue;
172 }
173
174 StringRef CustomFlagValueStr = Flag.substr(custom_flag::Prefix.size());
175 const custom_flag::ValueDetail *Detail =
176 ValueNameToValueDetail.get(CustomFlagValueStr);
177 if (Detail)
178 ClaimedCustomFlagValues.push_back(Detail);
179 else
180 UnclaimedCustomFlagValueStrs.push_back(CustomFlagValueStr);
181 }
182
183 // Set of custom flag declarations for which a value was passed in the flags
184 // list. This is used to, firstly, detect multiple values for the same flag
185 // declaration (in this case, the last one wins), and secondly, to detect
186 // which declarations had no value passed in (in this case, the default value
187 // is selected).
189
190 // Detect multiple values for the same flag declaration. Last one wins.
191 for (auto *CustomFlagValue : llvm::reverse(ClaimedCustomFlagValues)) {
192 if (!TriggeredCustomFlagDecls.insert(CustomFlagValue->Decl).second)
193 continue;
194 Result.push_back(std::string(custom_flag::Prefix) + CustomFlagValue->Name);
195 if (CustomFlagValue->MacroDefines)
196 MacroDefines.append(CustomFlagValue->MacroDefines->begin(),
197 CustomFlagValue->MacroDefines->end());
198 }
199
200 // Detect flag declarations with no value passed in. Select default value.
201 for (const auto &Decl : CustomFlagDecls) {
202 if (TriggeredCustomFlagDecls.contains(&Decl))
203 continue;
204 const custom_flag::ValueDetail &CustomFlagValue =
205 Decl.ValueList[*Decl.DefaultValueIdx];
206 Result.push_back(std::string(custom_flag::Prefix) + CustomFlagValue.Name);
207 if (CustomFlagValue.MacroDefines)
208 MacroDefines.append(CustomFlagValue.MacroDefines->begin(),
209 CustomFlagValue.MacroDefines->end());
210 }
211
212 DiagnoseUnclaimedMultilibCustomFlags(D, UnclaimedCustomFlagValueStrs,
213 CustomFlagDecls);
214
215 return {Result, MacroDefines};
216}
217
219 const Driver &D, const Multilib::flags_list &Flags,
221 llvm::SmallVector<StringRef> *CustomFlagMacroDefines) const {
222 auto [FlagsWithCustom, CFMacroDefines] = processCustomFlags(D, Flags);
223 llvm::StringSet<> FlagSet(expandFlags(FlagsWithCustom));
224 Selected.clear();
225 bool AnyErrors = false;
226
227 // Determining the list of macro defines depends only on the custom flags
228 // passed in. The library variants actually selected are not relevant in
229 // this. Therefore this assignment can take place before the selection
230 // happens.
231 if (CustomFlagMacroDefines)
232 *CustomFlagMacroDefines = std::move(CFMacroDefines);
233
234 // Decide which multilibs we're going to select at all.
235 llvm::DenseSet<StringRef> ExclusiveGroupsSelected;
236 for (const Multilib &M : llvm::reverse(Multilibs)) {
237 // If this multilib doesn't match all our flags, don't select it.
238 if (!llvm::all_of(M.flags(), [&FlagSet](const std::string &F) {
239 return FlagSet.contains(F);
240 }))
241 continue;
242
243 const std::string &group = M.exclusiveGroup();
244 if (!group.empty()) {
245 // If this multilib has the same ExclusiveGroup as one we've already
246 // selected, skip it. We're iterating in reverse order, so the group
247 // member we've selected already is preferred.
248 //
249 // Otherwise, add the group name to the set of groups we've already
250 // selected a member of.
251 auto [It, Inserted] = ExclusiveGroupsSelected.insert(group);
252 if (!Inserted)
253 continue;
254 }
255
256 // If this multilib is actually a placeholder containing an error message
257 // written by the multilib.yaml author, then set a flag that will cause a
258 // failure return. Our caller will display the error message.
259 if (M.isError())
260 AnyErrors = true;
261
262 // Select this multilib.
263 Selected.push_back(M);
264 }
265
266 // We iterated in reverse order, so now put Selected back the right way
267 // round.
268 std::reverse(Selected.begin(), Selected.end());
269
270 return !AnyErrors && !Selected.empty();
271}
272
273llvm::StringSet<>
275 llvm::StringSet<> Result;
276 for (const auto &F : InFlags)
277 Result.insert(F);
278 for (const FlagMatcher &M : FlagMatchers) {
279 std::string RegexString(M.Match);
280
281 // Make the regular expression match the whole string.
282 if (!StringRef(M.Match).starts_with("^"))
283 RegexString.insert(RegexString.begin(), '^');
284 if (!StringRef(M.Match).ends_with("$"))
285 RegexString.push_back('$');
286
287 const llvm::Regex Regex(RegexString);
288 assert(Regex.isValid());
289 if (llvm::any_of(InFlags,
290 [&Regex](StringRef F) { return Regex.match(F); })) {
291 Result.insert(M.Flags.begin(), M.Flags.end());
292 }
293 }
294 return Result;
295}
296
297namespace {
298
299// When updating this also update MULTILIB_VERSION in MultilibTest.cpp
300static const VersionTuple MultilibVersionCurrent(1, 0);
301
302struct MultilibSerialization {
303 std::string Dir; // if this record successfully selects a library dir
304 std::string Error; // if this record reports a fatal error message
305 std::vector<std::string> Flags;
306 std::string Group;
307};
308
309enum class MultilibGroupType {
310 /*
311 * The only group type currently supported is 'Exclusive', which indicates a
312 * group of multilibs of which at most one may be selected.
313 */
314 Exclusive,
315
316 /*
317 * Future possibility: a second group type indicating a set of library
318 * directories that are mutually _dependent_ rather than mutually exclusive:
319 * if you include one you must include them all.
320 *
321 * It might also be useful to allow groups to be members of other groups, so
322 * that a mutually exclusive group could contain a mutually dependent set of
323 * library directories, or vice versa.
324 *
325 * These additional features would need changes in the implementation, but
326 * the YAML schema is set up so they can be added without requiring changes
327 * in existing users' multilib.yaml files.
328 */
329};
330
331struct MultilibGroupSerialization {
332 std::string Name;
333 MultilibGroupType Type;
334};
335
336struct MultilibSetSerialization {
337 llvm::VersionTuple MultilibVersion;
341 SmallVector<custom_flag::Declaration> CustomFlagDeclarations;
342};
343
344} // end anonymous namespace
345
346LLVM_YAML_IS_SEQUENCE_VECTOR(MultilibSerialization)
347LLVM_YAML_IS_SEQUENCE_VECTOR(MultilibGroupSerialization)
348LLVM_YAML_IS_SEQUENCE_VECTOR(MultilibSet::FlagMatcher)
349LLVM_YAML_IS_SEQUENCE_VECTOR(custom_flag::ValueDetail)
350LLVM_YAML_IS_SEQUENCE_VECTOR(custom_flag::Declaration)
351
352template <> struct llvm::yaml::MappingTraits<MultilibSerialization> {
353 static void mapping(llvm::yaml::IO &io, MultilibSerialization &V) {
354 io.mapOptional("Dir", V.Dir);
355 io.mapOptional("Error", V.Error);
356 io.mapRequired("Flags", V.Flags);
357 io.mapOptional("Group", V.Group);
358 }
359 static std::string validate(IO &io, MultilibSerialization &V) {
360 if (V.Dir.empty() && V.Error.empty())
361 return "one of the 'Dir' and 'Error' keys must be specified";
362 if (!V.Dir.empty() && !V.Error.empty())
363 return "the 'Dir' and 'Error' keys may not both be specified";
364 if (StringRef(V.Dir).starts_with("/"))
365 return "paths must be relative but \"" + V.Dir + "\" starts with \"/\"";
366 return std::string{};
367 }
368};
369
370template <> struct llvm::yaml::ScalarEnumerationTraits<MultilibGroupType> {
371 static void enumeration(IO &io, MultilibGroupType &Val) {
372 io.enumCase(Val, "Exclusive", MultilibGroupType::Exclusive);
373 }
374};
375
376template <> struct llvm::yaml::MappingTraits<MultilibGroupSerialization> {
377 static void mapping(llvm::yaml::IO &io, MultilibGroupSerialization &V) {
378 io.mapRequired("Name", V.Name);
379 io.mapRequired("Type", V.Type);
380 }
381};
382
383template <> struct llvm::yaml::MappingTraits<MultilibSet::FlagMatcher> {
384 static void mapping(llvm::yaml::IO &io, MultilibSet::FlagMatcher &M) {
385 io.mapRequired("Match", M.Match);
386 io.mapRequired("Flags", M.Flags);
387 }
388 static std::string validate(IO &io, MultilibSet::FlagMatcher &M) {
389 llvm::Regex Regex(M.Match);
390 std::string RegexError;
391 if (!Regex.isValid(RegexError))
392 return RegexError;
393 if (M.Flags.empty())
394 return "value required for 'Flags'";
395 return std::string{};
396 }
397};
398
399template <>
400struct llvm::yaml::MappingContextTraits<custom_flag::ValueDetail,
401 llvm::SmallSet<std::string, 32>> {
402 static void mapping(llvm::yaml::IO &io, custom_flag::ValueDetail &V,
403 llvm::SmallSet<std::string, 32> &) {
404 io.mapRequired("Name", V.Name);
405 io.mapOptional("MacroDefines", V.MacroDefines);
406 }
407 static std::string validate(IO &io, custom_flag::ValueDetail &V,
408 llvm::SmallSet<std::string, 32> &NameSet) {
409 if (V.Name.empty())
410 return "custom flag value requires a name";
411 if (!NameSet.insert(V.Name).second)
412 return "duplicate custom flag value name: \"" + V.Name + "\"";
413 return {};
414 }
415};
416
417template <>
418struct llvm::yaml::MappingContextTraits<custom_flag::Declaration,
419 llvm::SmallSet<std::string, 32>> {
420 static void mapping(llvm::yaml::IO &io, custom_flag::Declaration &V,
421 llvm::SmallSet<std::string, 32> &NameSet) {
422 io.mapRequired("Name", V.Name);
423 io.mapRequired("Values", V.ValueList, NameSet);
424 std::string DefaultValueName;
425 io.mapRequired("Default", DefaultValueName);
426
427 for (auto [Idx, Value] : llvm::enumerate(V.ValueList)) {
428 Value.Decl = &V;
429 if (Value.Name == DefaultValueName) {
430 assert(!V.DefaultValueIdx);
431 V.DefaultValueIdx = Idx;
432 }
433 }
434 }
435 static std::string validate(IO &io, custom_flag::Declaration &V,
436 llvm::SmallSet<std::string, 32> &) {
437 if (V.Name.empty())
438 return "custom flag requires a name";
439 if (V.ValueList.empty())
440 return "custom flag must have at least one value";
441 if (!V.DefaultValueIdx)
442 return "custom flag must have a default value";
443 return {};
444 }
445};
446
447template <> struct llvm::yaml::MappingTraits<MultilibSetSerialization> {
448 static void mapping(llvm::yaml::IO &io, MultilibSetSerialization &M) {
449 io.mapRequired("MultilibVersion", M.MultilibVersion);
450 io.mapRequired("Variants", M.Multilibs);
451 io.mapOptional("Groups", M.Groups);
452 llvm::SmallSet<std::string, 32> NameSet;
453 io.mapOptionalWithContext("Flags", M.CustomFlagDeclarations, NameSet);
454 io.mapOptional("Mappings", M.FlagMatchers);
455 }
456 static std::string validate(IO &io, MultilibSetSerialization &M) {
457 if (M.MultilibVersion.empty())
458 return "missing required key 'MultilibVersion'";
459 if (M.MultilibVersion.getMajor() != MultilibVersionCurrent.getMajor())
460 return "multilib version " + M.MultilibVersion.getAsString() +
461 " is unsupported";
462 if (M.MultilibVersion.getMinor() > MultilibVersionCurrent.getMinor())
463 return "multilib version " + M.MultilibVersion.getAsString() +
464 " is unsupported";
465 for (const MultilibSerialization &Lib : M.Multilibs) {
466 if (!Lib.Group.empty()) {
467 bool Found = false;
468 for (const MultilibGroupSerialization &Group : M.Groups)
469 if (Group.Name == Lib.Group) {
470 Found = true;
471 break;
472 }
473 if (!Found)
474 return "multilib \"" + Lib.Dir +
475 "\" specifies undefined group name \"" + Lib.Group + "\"";
476 }
477 }
478 return std::string{};
479 }
480};
481
482llvm::ErrorOr<MultilibSet>
483MultilibSet::parseYaml(llvm::MemoryBufferRef Input,
484 llvm::SourceMgr::DiagHandlerTy DiagHandler,
485 void *DiagHandlerCtxt) {
486 MultilibSetSerialization MS;
487 llvm::yaml::Input YamlInput(Input, nullptr, DiagHandler, DiagHandlerCtxt);
488 YamlInput >> MS;
489 if (YamlInput.error())
490 return YamlInput.error();
491
492 multilib_list Multilibs;
493 Multilibs.reserve(MS.Multilibs.size());
494 for (const auto &M : MS.Multilibs) {
495 if (!M.Error.empty()) {
496 Multilibs.emplace_back("", "", "", M.Flags, M.Group, M.Error);
497 } else {
498 std::string Dir;
499 if (M.Dir != ".")
500 Dir = "/" + M.Dir;
501 // We transfer M.Group straight into the ExclusiveGroup parameter for the
502 // Multilib constructor. If we later support more than one type of group,
503 // we'll have to look up the group name in MS.Groups, check its type, and
504 // decide what to do here.
505 Multilibs.emplace_back(Dir, Dir, Dir, M.Flags, M.Group);
506 }
507 }
508
509 return MultilibSet(std::move(Multilibs), std::move(MS.FlagMatchers),
510 std::move(MS.CustomFlagDeclarations));
511}
512
513LLVM_DUMP_METHOD void MultilibSet::dump() const {
514 print(llvm::errs());
515}
516
517void MultilibSet::print(raw_ostream &OS) const {
518 for (const auto &M : *this)
519 OS << M << "\n";
520}
521
522raw_ostream &clang::driver::operator<<(raw_ostream &OS, const MultilibSet &MS) {
523 MS.print(OS);
524 return OS;
525}
526
529 : Name(Other.Name), ValueList(Other.ValueList),
530 DefaultValueIdx(Other.DefaultValueIdx) {
531 for (ValueDetail &Detail : ValueList)
532 Detail.Decl = this;
533}
534
536 : Name(std::move(Other.Name)), ValueList(std::move(Other.ValueList)),
537 DefaultValueIdx(std::move(Other.DefaultValueIdx)) {
538 for (ValueDetail &Detail : ValueList)
539 Detail.Decl = this;
540}
541
543 if (this == &Other)
544 return *this;
545 Name = Other.Name;
546 ValueList = Other.ValueList;
547 DefaultValueIdx = Other.DefaultValueIdx;
548 for (ValueDetail &Detail : ValueList)
549 Detail.Decl = this;
550 return *this;
551}
552
554 if (this == &Other)
555 return *this;
556 Name = std::move(Other.Name);
557 ValueList = std::move(Other.ValueList);
558 DefaultValueIdx = std::move(Other.DefaultValueIdx);
559 for (ValueDetail &Detail : ValueList)
560 Detail.Decl = this;
561 return *this;
562}
563} // namespace clang::driver::custom_flag
#define V(N, I)
Definition: ASTContext.h:3453
const Decl * D
unsigned Iter
Definition: HTMLLogger.cpp:153
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
static void DiagnoseUnclaimedMultilibCustomFlags(const Driver &D, const SmallVector< StringRef > &UnclaimedCustomFlagValues, const SmallVector< custom_flag::Declaration > &CustomFlagDecls)
Definition: Multilib.cpp:95
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
The base class of the type hierarchy.
Definition: Type.h:1828
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
Definition: Driver.h:99
See also MultilibSetBuilder for combining multilibs into a set.
Definition: Multilib.h:129
bool select(const Driver &D, const Multilib::flags_list &Flags, llvm::SmallVectorImpl< Multilib > &, llvm::SmallVector< StringRef > *=nullptr) const
Select compatible variants,.
Definition: Multilib.cpp:218
LLVM_DUMP_METHOD void dump() const
Definition: Multilib.cpp:513
llvm::function_ref< bool(const Multilib &)> FilterCallback
Definition: Multilib.h:135
unsigned size() const
Definition: Multilib.h:184
static llvm::ErrorOr< MultilibSet > parseYaml(llvm::MemoryBufferRef, llvm::SourceMgr::DiagHandlerTy=nullptr, void *DiagHandlerCtxt=nullptr)
Definition: Multilib.cpp:483
void print(raw_ostream &OS) const
Definition: Multilib.cpp:517
MultilibSet & FilterOut(FilterCallback F)
Filter out some subset of the Multilibs using a user defined callback.
Definition: Multilib.cpp:88
std::vector< Multilib > multilib_list
Definition: Multilib.h:131
llvm::StringSet expandFlags(const Multilib::flags_list &) const
Get the given flags plus flags found by matching them against the FlagMatchers and choosing the Flags...
Definition: Multilib.cpp:274
void push_back(const Multilib &M)
Add a completed Multilib to the set.
Definition: Multilib.cpp:93
std::pair< Multilib::flags_list, SmallVector< StringRef > > processCustomFlags(const Driver &D, const Multilib::flags_list &Flags) const
Process custom flags from Flags and returns an expanded flags list and a list of macro defines.
Definition: Multilib.cpp:153
This corresponds to a single GCC Multilib, or a segment of one controlled by a command line flag.
Definition: Multilib.h:35
const std::string & gccSuffix() const
Get the detected GCC installation path suffix for the multi-arch target variant.
Definition: Multilib.h:70
const std::string & osSuffix() const
Get the detected os path suffix for the multi-arch target variant.
Definition: Multilib.h:74
std::vector< std::string > flags_list
Definition: Multilib.h:37
Multilib(StringRef GCCSuffix={}, StringRef OSSuffix={}, StringRef IncludeSuffix={}, const flags_list &Flags=flags_list(), StringRef ExclusiveGroup={}, std::optional< StringRef > Error=std::nullopt)
GCCSuffix, OSSuffix & IncludeSuffix will be appended directly to the sysroot string so they must eith...
Definition: Multilib.cpp:30
const std::string & includeSuffix() const
Get the include directory suffix.
Definition: Multilib.h:78
LLVM_DUMP_METHOD void dump() const
Definition: Multilib.cpp:43
void print(raw_ostream &OS) const
print summary of the Multilib
Definition: Multilib.cpp:47
bool operator==(const Multilib &Other) const
Definition: Multilib.cpp:60
ValueNameToDetailMap(It FlagDeclsBegin, It FlagDeclsEnd)
Definition: Multilib.cpp:136
const ValueDetail * get(StringRef Key) const
Definition: Multilib.cpp:144
static constexpr StringRef Prefix
Definition: Multilib.h:125
raw_ostream & operator<<(raw_ostream &OS, const Multilib &M)
Definition: Multilib.cpp:83
The JSON file list parser is used to communicate input to InstallAPI.
@ Result
The result type of a method or function.
@ Other
Other implicit parameter.
Diagnostic wrappers for TextAPI types for error reporting.
Definition: Dominators.h:30
Uses regular expressions to simplify flags used for multilib selection.
Definition: Multilib.h:140
std::vector< std::string > Flags
Definition: Multilib.h:142
Declaration & operator=(const Declaration &)
Definition: Multilib.cpp:542
std::optional< size_t > DefaultValueIdx
Definition: Multilib.h:116
std::optional< SmallVector< std::string > > MacroDefines
Definition: Multilib.h:109
static std::string validate(IO &io, custom_flag::Declaration &V, llvm::SmallSet< std::string, 32 > &)
Definition: Multilib.cpp:435
static void mapping(llvm::yaml::IO &io, custom_flag::Declaration &V, llvm::SmallSet< std::string, 32 > &NameSet)
Definition: Multilib.cpp:420
static void mapping(llvm::yaml::IO &io, custom_flag::ValueDetail &V, llvm::SmallSet< std::string, 32 > &)
Definition: Multilib.cpp:402
static std::string validate(IO &io, custom_flag::ValueDetail &V, llvm::SmallSet< std::string, 32 > &NameSet)
Definition: Multilib.cpp:407
static void mapping(llvm::yaml::IO &io, MultilibGroupSerialization &V)
Definition: Multilib.cpp:377
static void mapping(llvm::yaml::IO &io, MultilibSerialization &V)
Definition: Multilib.cpp:353
static std::string validate(IO &io, MultilibSerialization &V)
Definition: Multilib.cpp:359
static void mapping(llvm::yaml::IO &io, MultilibSetSerialization &M)
Definition: Multilib.cpp:448
static std::string validate(IO &io, MultilibSetSerialization &M)
Definition: Multilib.cpp:456
static std::string validate(IO &io, MultilibSet::FlagMatcher &M)
Definition: Multilib.cpp:388
static void mapping(llvm::yaml::IO &io, MultilibSet::FlagMatcher &M)
Definition: Multilib.cpp:384
static void enumeration(IO &io, MultilibGroupType &Val)
Definition: Multilib.cpp:371