Path: blob/main/contrib/llvm-project/llvm/lib/Option/Option.cpp
35234 views
//===- Option.cpp - Abstract Driver Options -------------------------------===//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/StringRef.h"9#include "llvm/ADT/Twine.h"10#include "llvm/Config/llvm-config.h"11#include "llvm/Option/Arg.h"12#include "llvm/Option/ArgList.h"13#include "llvm/Option/Option.h"14#include "llvm/Option/OptTable.h"15#include "llvm/Support/Compiler.h"16#include "llvm/Support/Debug.h"17#include "llvm/Support/ErrorHandling.h"18#include "llvm/Support/raw_ostream.h"19#include <cassert>20#include <cstring>2122using namespace llvm;23using namespace llvm::opt;2425Option::Option(const OptTable::Info *info, const OptTable *owner)26: Info(info), Owner(owner) {27// Multi-level aliases are not supported. This just simplifies option28// tracking, it is not an inherent limitation.29assert((!Info || !getAlias().isValid() || !getAlias().getAlias().isValid()) &&30"Multi-level aliases are not supported.");3132if (Info && getAliasArgs()) {33assert(getAlias().isValid() && "Only alias options can have alias args.");34assert(getKind() == FlagClass && "Only Flag aliases can have alias args.");35assert(getAlias().getKind() != FlagClass &&36"Cannot provide alias args to a flag option.");37}38}3940void Option::print(raw_ostream &O, bool AddNewLine) const {41O << "<";42switch (getKind()) {43#define P(N) case N: O << #N; break44P(GroupClass);45P(InputClass);46P(UnknownClass);47P(FlagClass);48P(JoinedClass);49P(ValuesClass);50P(SeparateClass);51P(CommaJoinedClass);52P(MultiArgClass);53P(JoinedOrSeparateClass);54P(JoinedAndSeparateClass);55P(RemainingArgsClass);56P(RemainingArgsJoinedClass);57#undef P58}5960if (!Info->Prefixes.empty()) {61O << " Prefixes:[";62for (size_t I = 0, N = Info->Prefixes.size(); I != N; ++I)63O << '"' << Info->Prefixes[I] << (I == N - 1 ? "\"" : "\", ");64O << ']';65}6667O << " Name:\"" << getName() << '"';6869const Option Group = getGroup();70if (Group.isValid()) {71O << " Group:";72Group.print(O, /*AddNewLine=*/false);73}7475const Option Alias = getAlias();76if (Alias.isValid()) {77O << " Alias:";78Alias.print(O, /*AddNewLine=*/false);79}8081if (getKind() == MultiArgClass)82O << " NumArgs:" << getNumArgs();8384O << ">";85if (AddNewLine)86O << "\n";87}8889#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)90LLVM_DUMP_METHOD void Option::dump() const { print(dbgs()); }91#endif9293bool Option::matches(OptSpecifier Opt) const {94// Aliases are never considered in matching, look through them.95const Option Alias = getAlias();96if (Alias.isValid())97return Alias.matches(Opt);9899// Check exact match.100if (getID() == Opt.getID())101return true;102103const Option Group = getGroup();104if (Group.isValid())105return Group.matches(Opt);106return false;107}108109std::unique_ptr<Arg> Option::acceptInternal(const ArgList &Args,110StringRef Spelling,111unsigned &Index) const {112const size_t SpellingSize = Spelling.size();113const size_t ArgStringSize = StringRef(Args.getArgString(Index)).size();114switch (getKind()) {115case FlagClass: {116if (SpellingSize != ArgStringSize)117return nullptr;118return std::make_unique<Arg>(*this, Spelling, Index++);119}120case JoinedClass: {121const char *Value = Args.getArgString(Index) + SpellingSize;122return std::make_unique<Arg>(*this, Spelling, Index++, Value);123}124case CommaJoinedClass: {125// Always matches.126const char *Str = Args.getArgString(Index) + SpellingSize;127auto A = std::make_unique<Arg>(*this, Spelling, Index++);128129// Parse out the comma separated values.130const char *Prev = Str;131for (;; ++Str) {132char c = *Str;133134if (!c || c == ',') {135if (Prev != Str) {136char *Value = new char[Str - Prev + 1];137memcpy(Value, Prev, Str - Prev);138Value[Str - Prev] = '\0';139A->getValues().push_back(Value);140}141142if (!c)143break;144145Prev = Str + 1;146}147}148A->setOwnsValues(true);149150return A;151}152case SeparateClass:153// Matches iff this is an exact match.154if (SpellingSize != ArgStringSize)155return nullptr;156157Index += 2;158if (Index > Args.getNumInputArgStrings() ||159Args.getArgString(Index - 1) == nullptr)160return nullptr;161162return std::make_unique<Arg>(*this, Spelling, Index - 2,163Args.getArgString(Index - 1));164case MultiArgClass: {165// Matches iff this is an exact match.166if (SpellingSize != ArgStringSize)167return nullptr;168169Index += 1 + getNumArgs();170if (Index > Args.getNumInputArgStrings())171return nullptr;172173auto A = std::make_unique<Arg>(*this, Spelling, Index - 1 - getNumArgs(),174Args.getArgString(Index - getNumArgs()));175for (unsigned i = 1; i != getNumArgs(); ++i)176A->getValues().push_back(Args.getArgString(Index - getNumArgs() + i));177return A;178}179case JoinedOrSeparateClass: {180// If this is not an exact match, it is a joined arg.181if (SpellingSize != ArgStringSize) {182const char *Value = Args.getArgString(Index) + SpellingSize;183return std::make_unique<Arg>(*this, Spelling, Index++, Value);184}185186// Otherwise it must be separate.187Index += 2;188if (Index > Args.getNumInputArgStrings() ||189Args.getArgString(Index - 1) == nullptr)190return nullptr;191192return std::make_unique<Arg>(*this, Spelling, Index - 2,193Args.getArgString(Index - 1));194}195case JoinedAndSeparateClass:196// Always matches.197Index += 2;198if (Index > Args.getNumInputArgStrings() ||199Args.getArgString(Index - 1) == nullptr)200return nullptr;201202return std::make_unique<Arg>(*this, Spelling, Index - 2,203Args.getArgString(Index - 2) + SpellingSize,204Args.getArgString(Index - 1));205case RemainingArgsClass: {206// Matches iff this is an exact match.207if (SpellingSize != ArgStringSize)208return nullptr;209auto A = std::make_unique<Arg>(*this, Spelling, Index++);210while (Index < Args.getNumInputArgStrings() &&211Args.getArgString(Index) != nullptr)212A->getValues().push_back(Args.getArgString(Index++));213return A;214}215case RemainingArgsJoinedClass: {216auto A = std::make_unique<Arg>(*this, Spelling, Index);217if (SpellingSize != ArgStringSize) {218// An inexact match means there is a joined arg.219A->getValues().push_back(Args.getArgString(Index) + SpellingSize);220}221Index++;222while (Index < Args.getNumInputArgStrings() &&223Args.getArgString(Index) != nullptr)224A->getValues().push_back(Args.getArgString(Index++));225return A;226}227228default:229llvm_unreachable("Invalid option kind!");230}231}232233std::unique_ptr<Arg> Option::accept(const ArgList &Args, StringRef CurArg,234bool GroupedShortOption,235unsigned &Index) const {236auto A(GroupedShortOption && getKind() == FlagClass237? std::make_unique<Arg>(*this, CurArg, Index)238: acceptInternal(Args, CurArg, Index));239if (!A)240return nullptr;241242const Option &UnaliasedOption = getUnaliasedOption();243if (getID() == UnaliasedOption.getID())244return A;245246// "A" is an alias for a different flag. For most clients it's more convenient247// if this function returns unaliased Args, so create an unaliased arg for248// returning.249250// This creates a completely new Arg object for the unaliased Arg because251// the alias and the unaliased arg can have different Kinds and different252// Values (due to AliasArgs<>).253254// Get the spelling from the unaliased option.255StringRef UnaliasedSpelling = Args.MakeArgString(256Twine(UnaliasedOption.getPrefix()) + Twine(UnaliasedOption.getName()));257258// It's a bit weird that aliased and unaliased arg share one index, but259// the index is mostly use as a memory optimization in render().260// Due to this, ArgList::getArgString(A->getIndex()) will return the spelling261// of the aliased arg always, while A->getSpelling() returns either the262// unaliased or the aliased arg, depending on which Arg object it's called on.263auto UnaliasedA =264std::make_unique<Arg>(UnaliasedOption, UnaliasedSpelling, A->getIndex());265Arg *RawA = A.get();266UnaliasedA->setAlias(std::move(A));267268if (getKind() != FlagClass) {269// Values are usually owned by the ArgList. The exception are270// CommaJoined flags, where the Arg owns the values. For aliased flags,271// make the unaliased Arg the owner of the values.272// FIXME: There aren't many uses of CommaJoined -- try removing273// CommaJoined in favor of just calling StringRef::split(',') instead.274UnaliasedA->getValues() = RawA->getValues();275UnaliasedA->setOwnsValues(RawA->getOwnsValues());276RawA->setOwnsValues(false);277return UnaliasedA;278}279280// FlagClass aliases can have AliasArgs<>; add those to the unaliased arg.281if (const char *Val = getAliasArgs()) {282while (*Val != '\0') {283UnaliasedA->getValues().push_back(Val);284285// Move past the '\0' to the next argument.286Val += strlen(Val) + 1;287}288}289if (UnaliasedOption.getKind() == JoinedClass && !getAliasArgs())290// A Flag alias for a Joined option must provide an argument.291UnaliasedA->getValues().push_back("");292return UnaliasedA;293}294295296