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