297 lines · cpp
1//===- Option.cpp - Abstract Driver Options -------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/Option/Option.h"10#include "llvm/ADT/StringRef.h"11#include "llvm/ADT/Twine.h"12#include "llvm/Config/llvm-config.h"13#include "llvm/Option/Arg.h"14#include "llvm/Option/ArgList.h"15#include "llvm/Option/OptTable.h"16#include "llvm/Support/Compiler.h"17#include "llvm/Support/Debug.h"18#include "llvm/Support/ErrorHandling.h"19#include "llvm/Support/raw_ostream.h"20#include <cassert>21 22using namespace llvm;23using namespace llvm::opt;24 25Option::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.29 assert((!Info || !getAlias().isValid() || !getAlias().getAlias().isValid()) &&30 "Multi-level aliases are not supported.");31 32 if (Info && getAliasArgs()) {33 assert(getAlias().isValid() && "Only alias options can have alias args.");34 assert(getKind() == FlagClass && "Only Flag aliases can have alias args.");35 assert(getAlias().getKind() != FlagClass &&36 "Cannot provide alias args to a flag option.");37 }38}39 40void Option::print(raw_ostream &O, bool AddNewLine) const {41 O << "<";42 switch (getKind()) {43#define P(N) case N: O << #N; break44 P(GroupClass);45 P(InputClass);46 P(UnknownClass);47 P(FlagClass);48 P(JoinedClass);49 P(ValuesClass);50 P(SeparateClass);51 P(CommaJoinedClass);52 P(MultiArgClass);53 P(JoinedOrSeparateClass);54 P(JoinedAndSeparateClass);55 P(RemainingArgsClass);56 P(RemainingArgsJoinedClass);57#undef P58 }59 60 if (!Info->hasNoPrefix()) {61 O << " Prefixes:[";62 for (size_t I = 0, N = Info->getNumPrefixes(Owner->getPrefixesTable());63 I != N; ++I)64 O << '"'65 << Info->getPrefix(Owner->getStrTable(), Owner->getPrefixesTable(), I)66 << (I == N - 1 ? "\"" : "\", ");67 O << ']';68 }69 70 O << " Name:\"" << getName() << '"';71 72 const Option Group = getGroup();73 if (Group.isValid()) {74 O << " Group:";75 Group.print(O, /*AddNewLine=*/false);76 }77 78 const Option Alias = getAlias();79 if (Alias.isValid()) {80 O << " Alias:";81 Alias.print(O, /*AddNewLine=*/false);82 }83 84 if (getKind() == MultiArgClass)85 O << " NumArgs:" << getNumArgs();86 87 O << ">";88 if (AddNewLine)89 O << "\n";90}91 92#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)93LLVM_DUMP_METHOD void Option::dump() const { print(dbgs()); }94#endif95 96bool Option::matches(OptSpecifier Opt) const {97 // Aliases are never considered in matching, look through them.98 const Option Alias = getAlias();99 if (Alias.isValid())100 return Alias.matches(Opt);101 102 // Check exact match.103 if (getID() == Opt.getID())104 return true;105 106 const Option Group = getGroup();107 if (Group.isValid())108 return Group.matches(Opt);109 return false;110}111 112std::unique_ptr<Arg> Option::acceptInternal(const ArgList &Args,113 StringRef Spelling,114 unsigned &Index) const {115 const size_t SpellingSize = Spelling.size();116 const size_t ArgStringSize = StringRef(Args.getArgString(Index)).size();117 switch (getKind()) {118 case FlagClass: {119 if (SpellingSize != ArgStringSize)120 return nullptr;121 return std::make_unique<Arg>(*this, Spelling, Index++);122 }123 case JoinedClass: {124 const char *Value = Args.getArgString(Index) + SpellingSize;125 return std::make_unique<Arg>(*this, Spelling, Index++, Value);126 }127 case CommaJoinedClass: {128 // Always matches.129 const char *Str = Args.getArgString(Index) + SpellingSize;130 auto A = std::make_unique<Arg>(*this, Spelling, Index++);131 132 // Parse out the comma separated values.133 const char *Prev = Str;134 for (;; ++Str) {135 char c = *Str;136 137 if (!c || c == ',') {138 if (Prev != Str) {139 char *Value = new char[Str - Prev + 1];140 memcpy(Value, Prev, Str - Prev);141 Value[Str - Prev] = '\0';142 A->getValues().push_back(Value);143 }144 145 if (!c)146 break;147 148 Prev = Str + 1;149 }150 }151 A->setOwnsValues(true);152 153 return A;154 }155 case SeparateClass:156 // Matches iff this is an exact match.157 if (SpellingSize != ArgStringSize)158 return nullptr;159 160 Index += 2;161 if (Index > Args.getNumInputArgStrings() ||162 Args.getArgString(Index - 1) == nullptr)163 return nullptr;164 165 return std::make_unique<Arg>(*this, Spelling, Index - 2,166 Args.getArgString(Index - 1));167 case MultiArgClass: {168 // Matches iff this is an exact match.169 if (SpellingSize != ArgStringSize)170 return nullptr;171 172 Index += 1 + getNumArgs();173 if (Index > Args.getNumInputArgStrings())174 return nullptr;175 176 auto A = std::make_unique<Arg>(*this, Spelling, Index - 1 - getNumArgs(),177 Args.getArgString(Index - getNumArgs()));178 for (unsigned i = 1; i != getNumArgs(); ++i)179 A->getValues().push_back(Args.getArgString(Index - getNumArgs() + i));180 return A;181 }182 case JoinedOrSeparateClass: {183 // If this is not an exact match, it is a joined arg.184 if (SpellingSize != ArgStringSize) {185 const char *Value = Args.getArgString(Index) + SpellingSize;186 return std::make_unique<Arg>(*this, Spelling, Index++, Value);187 }188 189 // Otherwise it must be separate.190 Index += 2;191 if (Index > Args.getNumInputArgStrings() ||192 Args.getArgString(Index - 1) == nullptr)193 return nullptr;194 195 return std::make_unique<Arg>(*this, Spelling, Index - 2,196 Args.getArgString(Index - 1));197 }198 case JoinedAndSeparateClass:199 // Always matches.200 Index += 2;201 if (Index > Args.getNumInputArgStrings() ||202 Args.getArgString(Index - 1) == nullptr)203 return nullptr;204 205 return std::make_unique<Arg>(*this, Spelling, Index - 2,206 Args.getArgString(Index - 2) + SpellingSize,207 Args.getArgString(Index - 1));208 case RemainingArgsClass: {209 // Matches iff this is an exact match.210 if (SpellingSize != ArgStringSize)211 return nullptr;212 auto A = std::make_unique<Arg>(*this, Spelling, Index++);213 while (Index < Args.getNumInputArgStrings() &&214 Args.getArgString(Index) != nullptr)215 A->getValues().push_back(Args.getArgString(Index++));216 return A;217 }218 case RemainingArgsJoinedClass: {219 auto A = std::make_unique<Arg>(*this, Spelling, Index);220 if (SpellingSize != ArgStringSize) {221 // An inexact match means there is a joined arg.222 A->getValues().push_back(Args.getArgString(Index) + SpellingSize);223 }224 Index++;225 while (Index < Args.getNumInputArgStrings() &&226 Args.getArgString(Index) != nullptr)227 A->getValues().push_back(Args.getArgString(Index++));228 return A;229 }230 231 default:232 llvm_unreachable("Invalid option kind!");233 }234}235 236std::unique_ptr<Arg> Option::accept(const ArgList &Args, StringRef CurArg,237 bool GroupedShortOption,238 unsigned &Index) const {239 auto A(GroupedShortOption && getKind() == FlagClass240 ? std::make_unique<Arg>(*this, CurArg, Index)241 : acceptInternal(Args, CurArg, Index));242 if (!A)243 return nullptr;244 245 const Option &UnaliasedOption = getUnaliasedOption();246 if (getID() == UnaliasedOption.getID())247 return A;248 249 // "A" is an alias for a different flag. For most clients it's more convenient250 // if this function returns unaliased Args, so create an unaliased arg for251 // returning.252 253 // This creates a completely new Arg object for the unaliased Arg because254 // the alias and the unaliased arg can have different Kinds and different255 // Values (due to AliasArgs<>).256 257 // Get the spelling from the unaliased option.258 StringRef UnaliasedSpelling = Args.MakeArgString(259 Twine(UnaliasedOption.getPrefix()) + Twine(UnaliasedOption.getName()));260 261 // It's a bit weird that aliased and unaliased arg share one index, but262 // the index is mostly use as a memory optimization in render().263 // Due to this, ArgList::getArgString(A->getIndex()) will return the spelling264 // of the aliased arg always, while A->getSpelling() returns either the265 // unaliased or the aliased arg, depending on which Arg object it's called on.266 auto UnaliasedA =267 std::make_unique<Arg>(UnaliasedOption, UnaliasedSpelling, A->getIndex());268 Arg *RawA = A.get();269 UnaliasedA->setAlias(std::move(A));270 271 if (getKind() != FlagClass) {272 // Values are usually owned by the ArgList. The exception are273 // CommaJoined flags, where the Arg owns the values. For aliased flags,274 // make the unaliased Arg the owner of the values.275 // FIXME: There aren't many uses of CommaJoined -- try removing276 // CommaJoined in favor of just calling StringRef::split(',') instead.277 UnaliasedA->getValues() = RawA->getValues();278 UnaliasedA->setOwnsValues(RawA->getOwnsValues());279 RawA->setOwnsValues(false);280 return UnaliasedA;281 }282 283 // FlagClass aliases can have AliasArgs<>; add those to the unaliased arg.284 if (const char *Val = getAliasArgs()) {285 while (*Val != '\0') {286 UnaliasedA->getValues().push_back(Val);287 288 // Move past the '\0' to the next argument.289 Val += strlen(Val) + 1;290 }291 }292 if (UnaliasedOption.getKind() == JoinedClass && !getAliasArgs())293 // A Flag alias for a Joined option must provide an argument.294 UnaliasedA->getValues().push_back("");295 return UnaliasedA;296}297