LCOV - code coverage report
Current view: top level - lib/Option - Option.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 89 124 71.8 %
Date: 2018-06-17 00:07:59 Functions: 3 4 75.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- Option.cpp - Abstract Driver Options -------------------------------===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : 
      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/Option.h"
      16             : #include "llvm/Option/OptTable.h"
      17             : #include "llvm/Support/Compiler.h"
      18             : #include "llvm/Support/Debug.h"
      19             : #include "llvm/Support/ErrorHandling.h"
      20             : #include "llvm/Support/raw_ostream.h"
      21             : #include <cassert>
      22             : #include <cstring>
      23             : 
      24             : using namespace llvm;
      25             : using namespace llvm::opt;
      26             : 
      27   133339180 : Option::Option(const OptTable::Info *info, const OptTable *owner)
      28   133339180 :   : Info(info), Owner(owner) {
      29             :   // Multi-level aliases are not supported. This just simplifies option
      30             :   // tracking, it is not an inherent limitation.
      31             :   assert((!Info || !getAlias().isValid() || !getAlias().getAlias().isValid()) &&
      32             :          "Multi-level aliases are not supported.");
      33             : 
      34             :   if (Info && getAliasArgs()) {
      35             :     assert(getAlias().isValid() && "Only alias options can have alias args.");
      36             :     assert(getKind() == FlagClass && "Only Flag aliases can have alias args.");
      37             :     assert(getAlias().getKind() != FlagClass &&
      38             :            "Cannot provide alias args to a flag option.");
      39             :   }
      40   133339180 : }
      41             : 
      42           0 : void Option::print(raw_ostream &O) const {
      43           0 :   O << "<";
      44           0 :   switch (getKind()) {
      45             : #define P(N) case N: O << #N; break
      46           0 :     P(GroupClass);
      47           0 :     P(InputClass);
      48           0 :     P(UnknownClass);
      49           0 :     P(FlagClass);
      50           0 :     P(JoinedClass);
      51           0 :     P(ValuesClass);
      52           0 :     P(SeparateClass);
      53           0 :     P(CommaJoinedClass);
      54           0 :     P(MultiArgClass);
      55           0 :     P(JoinedOrSeparateClass);
      56           0 :     P(JoinedAndSeparateClass);
      57           0 :     P(RemainingArgsClass);
      58           0 :     P(RemainingArgsJoinedClass);
      59             : #undef P
      60             :   }
      61             : 
      62           0 :   if (Info->Prefixes) {
      63           0 :     O << " Prefixes:[";
      64           0 :     for (const char *const *Pre = Info->Prefixes; *Pre != nullptr; ++Pre) {
      65           0 :       O << '"' << *Pre << (*(Pre + 1) == nullptr ? "\"" : "\", ");
      66             :     }
      67             :     O << ']';
      68             :   }
      69             : 
      70           0 :   O << " Name:\"" << getName() << '"';
      71             : 
      72           0 :   const Option Group = getGroup();
      73           0 :   if (Group.isValid()) {
      74           0 :     O << " Group:";
      75           0 :     Group.print(O);
      76             :   }
      77             : 
      78           0 :   const Option Alias = getAlias();
      79           0 :   if (Alias.isValid()) {
      80           0 :     O << " Alias:";
      81           0 :     Alias.print(O);
      82             :   }
      83             : 
      84           0 :   if (getKind() == MultiArgClass)
      85           0 :     O << " NumArgs:" << getNumArgs();
      86             : 
      87           0 :   O << ">\n";
      88           0 : }
      89             : 
      90             : #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
      91             : LLVM_DUMP_METHOD void Option::dump() const { print(dbgs()); }
      92             : #endif
      93             : 
      94    61476115 : bool Option::matches(OptSpecifier Opt) const {
      95             :   // Aliases are never considered in matching, look through them.
      96    61476111 :   const Option Alias = getAlias();
      97    61476111 :   if (Alias.isValid())
      98        3759 :     return Alias.matches(Opt);
      99             : 
     100             :   // Check exact match.
     101   122944704 :   if (getID() == Opt.getID())
     102             :     return true;
     103             : 
     104    59208759 :   const Option Group = getGroup();
     105    59208759 :   if (Group.isValid())
     106    37187856 :     return Group.matches(Opt);
     107             :   return false;
     108             : }
     109             : 
     110     1759953 : Arg *Option::accept(const ArgList &Args,
     111             :                     unsigned &Index,
     112             :                     unsigned ArgSize) const {
     113     1759953 :   const Option &UnaliasedOption = getUnaliasedOption();
     114             :   StringRef Spelling;
     115             :   // If the option was an alias, get the spelling from the unaliased one.
     116     3519906 :   if (getID() == UnaliasedOption.getID()) {
     117     1726006 :     Spelling = StringRef(Args.getArgString(Index), ArgSize);
     118             :   } else {
     119      101841 :     Spelling = Args.MakeArgString(Twine(UnaliasedOption.getPrefix()) +
     120       67894 :                                   Twine(UnaliasedOption.getName()));
     121             :   }
     122             : 
     123     3519904 :   switch (getKind()) {
     124      383640 :   case FlagClass: {
     125      383640 :     if (ArgSize != strlen(Args.getArgString(Index)))
     126             :       return nullptr;
     127             : 
     128      382236 :     Arg *A = new Arg(UnaliasedOption, Spelling, Index++);
     129      764470 :     if (getAliasArgs()) {
     130         546 :       const char *Val = getAliasArgs();
     131        1638 :       while (*Val != '\0') {
     132         546 :         A->getValues().push_back(Val);
     133             : 
     134             :         // Move past the '\0' to the next argument.
     135         546 :         Val += strlen(Val) + 1;
     136             :       }
     137             :     }
     138             : 
     139      382782 :     if (UnaliasedOption.getKind() == JoinedClass && !getAliasArgs())
     140             :       // A Flag alias for a Joined option must provide an argument.
     141           1 :       A->getValues().push_back("");
     142             : 
     143             :     return A;
     144             :   }
     145      106343 :   case JoinedClass: {
     146      106343 :     const char *Value = Args.getArgString(Index) + ArgSize;
     147      106343 :     return new Arg(UnaliasedOption, Spelling, Index++, Value);
     148             :   }
     149        6394 :   case CommaJoinedClass: {
     150             :     // Always matches.
     151        6394 :     const char *Str = Args.getArgString(Index) + ArgSize;
     152        6394 :     Arg *A = new Arg(UnaliasedOption, Spelling, Index++);
     153             : 
     154             :     // Parse out the comma separated values.
     155             :     const char *Prev = Str;
     156      120232 :     for (;; ++Str) {
     157      126626 :       char c = *Str;
     158             : 
     159      126626 :       if (!c || c == ',') {
     160        7133 :         if (Prev != Str) {
     161        7125 :           char *Value = new char[Str - Prev + 1];
     162        7125 :           memcpy(Value, Prev, Str - Prev);
     163        7125 :           Value[Str - Prev] = '\0';
     164        7125 :           A->getValues().push_back(Value);
     165             :         }
     166             : 
     167        7133 :         if (!c)
     168             :           break;
     169             : 
     170         739 :         Prev = Str + 1;
     171             :       }
     172      120232 :     }
     173             :     A->setOwnsValues(true);
     174             : 
     175        6394 :     return A;
     176             :   }
     177      136239 :   case SeparateClass:
     178             :     // Matches iff this is an exact match.
     179             :     // FIXME: Avoid strlen.
     180      136239 :     if (ArgSize != strlen(Args.getArgString(Index)))
     181             :       return nullptr;
     182             : 
     183      136237 :     Index += 2;
     184      272470 :     if (Index > Args.getNumInputArgStrings() ||
     185      136234 :         Args.getArgString(Index - 1) == nullptr)
     186             :       return nullptr;
     187             : 
     188             :     return new Arg(UnaliasedOption, Spelling,
     189      136233 :                    Index - 2, Args.getArgString(Index - 1));
     190           6 :   case MultiArgClass: {
     191             :     // Matches iff this is an exact match.
     192             :     // FIXME: Avoid strlen.
     193           6 :     if (ArgSize != strlen(Args.getArgString(Index)))
     194             :       return nullptr;
     195             : 
     196          12 :     Index += 1 + getNumArgs();
     197           6 :     if (Index > Args.getNumInputArgStrings())
     198             :       return nullptr;
     199             : 
     200          12 :     Arg *A = new Arg(UnaliasedOption, Spelling, Index - 1 - getNumArgs(),
     201          12 :                       Args.getArgString(Index - getNumArgs()));
     202          42 :     for (unsigned i = 1; i != getNumArgs(); ++i)
     203          10 :       A->getValues().push_back(Args.getArgString(Index - getNumArgs() + i));
     204             :     return A;
     205             :   }
     206     1126428 :   case JoinedOrSeparateClass: {
     207             :     // If this is not an exact match, it is a joined arg.
     208             :     // FIXME: Avoid strlen.
     209     1126428 :     if (ArgSize != strlen(Args.getArgString(Index))) {
     210      643890 :       const char *Value = Args.getArgString(Index) + ArgSize;
     211      643890 :       return new Arg(*this, Spelling, Index++, Value);
     212             :     }
     213             : 
     214             :     // Otherwise it must be separate.
     215      482538 :     Index += 2;
     216      965066 :     if (Index > Args.getNumInputArgStrings() ||
     217      482528 :         Args.getArgString(Index - 1) == nullptr)
     218             :       return nullptr;
     219             : 
     220             :     return new Arg(UnaliasedOption, Spelling,
     221      482528 :                    Index - 2, Args.getArgString(Index - 1));
     222             :   }
     223          27 :   case JoinedAndSeparateClass:
     224             :     // Always matches.
     225          27 :     Index += 2;
     226          54 :     if (Index > Args.getNumInputArgStrings() ||
     227          27 :         Args.getArgString(Index - 1) == nullptr)
     228             :       return nullptr;
     229             : 
     230          27 :     return new Arg(UnaliasedOption, Spelling, Index - 2,
     231          27 :                    Args.getArgString(Index - 2) + ArgSize,
     232          81 :                    Args.getArgString(Index - 1));
     233         861 :   case RemainingArgsClass: {
     234             :     // Matches iff this is an exact match.
     235             :     // FIXME: Avoid strlen.
     236         861 :     if (ArgSize != strlen(Args.getArgString(Index)))
     237             :       return nullptr;
     238         856 :     Arg *A = new Arg(UnaliasedOption, Spelling, Index++);
     239        3493 :     while (Index < Args.getNumInputArgStrings() &&
     240         879 :            Args.getArgString(Index) != nullptr)
     241         879 :       A->getValues().push_back(Args.getArgString(Index++));
     242             :     return A;
     243             :   }
     244          14 :   case RemainingArgsJoinedClass: {
     245          14 :     Arg *A = new Arg(UnaliasedOption, Spelling, Index);
     246          14 :     if (ArgSize != strlen(Args.getArgString(Index))) {
     247             :       // An inexact match means there is a joined arg.
     248           4 :       A->getValues().push_back(Args.getArgString(Index) + ArgSize);
     249             :     }
     250          14 :     Index++;
     251          85 :     while (Index < Args.getNumInputArgStrings() &&
     252          25 :            Args.getArgString(Index) != nullptr)
     253          23 :       A->getValues().push_back(Args.getArgString(Index++));
     254             :     return A;
     255             :   }
     256             : 
     257           0 :   default:
     258           0 :     llvm_unreachable("Invalid option kind!");
     259             :   }
     260             : }

Generated by: LCOV version 1.13