Path: blob/main/contrib/llvm-project/llvm/lib/Option/ArgList.cpp
35234 views
//===- ArgList.cpp - Argument List Management -----------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/ADT/ArrayRef.h"9#include "llvm/ADT/SmallVector.h"10#include "llvm/ADT/STLExtras.h"11#include "llvm/ADT/StringRef.h"12#include "llvm/ADT/Twine.h"13#include "llvm/Config/llvm-config.h"14#include "llvm/Option/Arg.h"15#include "llvm/Option/ArgList.h"16#include "llvm/Option/Option.h"17#include "llvm/Option/OptSpecifier.h"18#include "llvm/Support/Compiler.h"19#include "llvm/Support/Debug.h"20#include "llvm/Support/raw_ostream.h"21#include <algorithm>22#include <cassert>23#include <memory>24#include <string>25#include <utility>26#include <vector>2728using namespace llvm;29using namespace llvm::opt;3031void ArgList::append(Arg *A) {32Args.push_back(A);3334// Update ranges for the option and all of its groups.35for (Option O = A->getOption().getUnaliasedOption(); O.isValid();36O = O.getGroup()) {37auto &R =38OptRanges.insert(std::make_pair(O.getID(), emptyRange())).first->second;39R.first = std::min<unsigned>(R.first, Args.size() - 1);40R.second = Args.size();41}42}4344void ArgList::eraseArg(OptSpecifier Id) {45// Zero out the removed entries but keep them around so that we don't46// need to invalidate OptRanges.47for (Arg *const &A : filtered(Id)) {48// Avoid the need for a non-const filtered iterator variant.49Arg **ArgsBegin = Args.data();50ArgsBegin[&A - ArgsBegin] = nullptr;51}52OptRanges.erase(Id.getID());53}5455ArgList::OptRange56ArgList::getRange(std::initializer_list<OptSpecifier> Ids) const {57OptRange R = emptyRange();58for (auto Id : Ids) {59auto I = OptRanges.find(Id.getID());60if (I != OptRanges.end()) {61R.first = std::min(R.first, I->second.first);62R.second = std::max(R.second, I->second.second);63}64}65// Map an empty {-1, 0} range to {0, 0} so it can be used to form iterators.66if (R.first == -1u)67R.first = 0;68return R;69}7071bool ArgList::hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default) const {72if (Arg *A = getLastArg(Pos, Neg))73return A->getOption().matches(Pos);74return Default;75}7677bool ArgList::hasFlagNoClaim(OptSpecifier Pos, OptSpecifier Neg,78bool Default) const {79if (Arg *A = getLastArgNoClaim(Pos, Neg))80return A->getOption().matches(Pos);81return Default;82}8384bool ArgList::hasFlag(OptSpecifier Pos, OptSpecifier PosAlias, OptSpecifier Neg,85bool Default) const {86if (Arg *A = getLastArg(Pos, PosAlias, Neg))87return A->getOption().matches(Pos) || A->getOption().matches(PosAlias);88return Default;89}9091StringRef ArgList::getLastArgValue(OptSpecifier Id, StringRef Default) const {92if (Arg *A = getLastArg(Id))93return A->getValue();94return Default;95}9697std::vector<std::string> ArgList::getAllArgValues(OptSpecifier Id) const {98SmallVector<const char *, 16> Values;99AddAllArgValues(Values, Id);100return std::vector<std::string>(Values.begin(), Values.end());101}102103void ArgList::addOptInFlag(ArgStringList &Output, OptSpecifier Pos,104OptSpecifier Neg) const {105if (Arg *A = getLastArg(Pos, Neg))106if (A->getOption().matches(Pos))107A->render(*this, Output);108}109110void ArgList::AddAllArgsExcept(ArgStringList &Output,111ArrayRef<OptSpecifier> Ids,112ArrayRef<OptSpecifier> ExcludeIds) const {113for (const Arg *Arg : *this) {114bool Excluded = false;115for (OptSpecifier Id : ExcludeIds) {116if (Arg->getOption().matches(Id)) {117Excluded = true;118break;119}120}121if (!Excluded) {122for (OptSpecifier Id : Ids) {123if (Arg->getOption().matches(Id)) {124Arg->claim();125Arg->render(*this, Output);126break;127}128}129}130}131}132133/// This is a nicer interface when you don't have a list of Ids to exclude.134void ArgList::addAllArgs(ArgStringList &Output,135ArrayRef<OptSpecifier> Ids) const {136ArrayRef<OptSpecifier> Exclude = std::nullopt;137AddAllArgsExcept(Output, Ids, Exclude);138}139140void ArgList::AddAllArgs(ArgStringList &Output, OptSpecifier Id0) const {141for (auto *Arg : filtered(Id0)) {142Arg->claim();143Arg->render(*this, Output);144}145}146147void ArgList::AddAllArgValues(ArgStringList &Output, OptSpecifier Id0,148OptSpecifier Id1, OptSpecifier Id2) const {149for (auto *Arg : filtered(Id0, Id1, Id2)) {150Arg->claim();151const auto &Values = Arg->getValues();152Output.append(Values.begin(), Values.end());153}154}155156void ArgList::AddAllArgsTranslated(ArgStringList &Output, OptSpecifier Id0,157const char *Translation,158bool Joined) const {159for (auto *Arg : filtered(Id0)) {160Arg->claim();161162if (Joined) {163Output.push_back(MakeArgString(StringRef(Translation) +164Arg->getValue(0)));165} else {166Output.push_back(Translation);167Output.push_back(Arg->getValue(0));168}169}170}171172void ArgList::ClaimAllArgs(OptSpecifier Id0) const {173for (auto *Arg : filtered(Id0))174Arg->claim();175}176177void ArgList::ClaimAllArgs() const {178for (auto *Arg : *this)179if (!Arg->isClaimed())180Arg->claim();181}182183const char *ArgList::GetOrMakeJoinedArgString(unsigned Index,184StringRef LHS,185StringRef RHS) const {186StringRef Cur = getArgString(Index);187if (Cur.size() == LHS.size() + RHS.size() && Cur.starts_with(LHS) &&188Cur.ends_with(RHS))189return Cur.data();190191return MakeArgString(LHS + RHS);192}193194void ArgList::print(raw_ostream &O) const {195for (Arg *A : *this) {196O << "* ";197A->print(O);198}199}200201#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)202LLVM_DUMP_METHOD void ArgList::dump() const { print(dbgs()); }203#endif204205void InputArgList::releaseMemory() {206// An InputArgList always owns its arguments.207for (Arg *A : *this)208delete A;209}210211InputArgList::InputArgList(const char* const *ArgBegin,212const char* const *ArgEnd)213: NumInputArgStrings(ArgEnd - ArgBegin) {214ArgStrings.append(ArgBegin, ArgEnd);215}216217unsigned InputArgList::MakeIndex(StringRef String0) const {218unsigned Index = ArgStrings.size();219220// Tuck away so we have a reliable const char *.221SynthesizedStrings.push_back(std::string(String0));222ArgStrings.push_back(SynthesizedStrings.back().c_str());223224return Index;225}226227unsigned InputArgList::MakeIndex(StringRef String0,228StringRef String1) const {229unsigned Index0 = MakeIndex(String0);230unsigned Index1 = MakeIndex(String1);231assert(Index0 + 1 == Index1 && "Unexpected non-consecutive indices!");232(void) Index1;233return Index0;234}235236const char *InputArgList::MakeArgStringRef(StringRef Str) const {237return getArgString(MakeIndex(Str));238}239240DerivedArgList::DerivedArgList(const InputArgList &BaseArgs)241: BaseArgs(BaseArgs) {}242243const char *DerivedArgList::MakeArgStringRef(StringRef Str) const {244return BaseArgs.MakeArgString(Str);245}246247void DerivedArgList::AddSynthesizedArg(Arg *A) {248SynthesizedArgs.push_back(std::unique_ptr<Arg>(A));249}250251Arg *DerivedArgList::MakeFlagArg(const Arg *BaseArg, const Option Opt) const {252SynthesizedArgs.push_back(253std::make_unique<Arg>(Opt, MakeArgString(Opt.getPrefix() + Opt.getName()),254BaseArgs.MakeIndex(Opt.getName()), BaseArg));255return SynthesizedArgs.back().get();256}257258Arg *DerivedArgList::MakePositionalArg(const Arg *BaseArg, const Option Opt,259StringRef Value) const {260unsigned Index = BaseArgs.MakeIndex(Value);261SynthesizedArgs.push_back(262std::make_unique<Arg>(Opt, MakeArgString(Opt.getPrefix() + Opt.getName()),263Index, BaseArgs.getArgString(Index), BaseArg));264return SynthesizedArgs.back().get();265}266267Arg *DerivedArgList::MakeSeparateArg(const Arg *BaseArg, const Option Opt,268StringRef Value) const {269unsigned Index = BaseArgs.MakeIndex(Opt.getName(), Value);270SynthesizedArgs.push_back(271std::make_unique<Arg>(Opt, MakeArgString(Opt.getPrefix() + Opt.getName()),272Index, BaseArgs.getArgString(Index + 1), BaseArg));273return SynthesizedArgs.back().get();274}275276Arg *DerivedArgList::MakeJoinedArg(const Arg *BaseArg, const Option Opt,277StringRef Value) const {278unsigned Index = BaseArgs.MakeIndex((Opt.getName() + Value).str());279SynthesizedArgs.push_back(std::make_unique<Arg>(280Opt, MakeArgString(Opt.getPrefix() + Opt.getName()), Index,281BaseArgs.getArgString(Index) + Opt.getName().size(), BaseArg));282return SynthesizedArgs.back().get();283}284285286