LCOV - code coverage report
Current view: top level - lib/Option - Option.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 92 127 72.4 %
Date: 2017-09-14 15:23:50 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/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    99837319 : Option::Option(const OptTable::Info *info, const OptTable *owner)
      27    99837319 :   : 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    99837319 : }
      40             : 
      41           0 : void Option::print(raw_ostream &O) const {
      42           0 :   O << "<";
      43           0 :   switch (getKind()) {
      44             : #define P(N) case N: O << #N; break
      45           0 :     P(GroupClass);
      46           0 :     P(InputClass);
      47           0 :     P(UnknownClass);
      48           0 :     P(FlagClass);
      49           0 :     P(JoinedClass);
      50           0 :     P(ValuesClass);
      51           0 :     P(SeparateClass);
      52           0 :     P(CommaJoinedClass);
      53           0 :     P(MultiArgClass);
      54           0 :     P(JoinedOrSeparateClass);
      55           0 :     P(JoinedAndSeparateClass);
      56           0 :     P(RemainingArgsClass);
      57           0 :     P(RemainingArgsJoinedClass);
      58             : #undef P
      59             :   }
      60             : 
      61           0 :   if (Info->Prefixes) {
      62           0 :     O << " Prefixes:[";
      63           0 :     for (const char *const *Pre = Info->Prefixes; *Pre != nullptr; ++Pre) {
      64           0 :       O << '"' << *Pre << (*(Pre + 1) == nullptr ? "\"" : "\", ");
      65             :     }
      66             :     O << ']';
      67             :   }
      68             : 
      69           0 :   O << " Name:\"" << getName() << '"';
      70             : 
      71           0 :   const Option Group = getGroup();
      72           0 :   if (Group.isValid()) {
      73           0 :     O << " Group:";
      74           0 :     Group.print(O);
      75             :   }
      76             : 
      77           0 :   const Option Alias = getAlias();
      78           0 :   if (Alias.isValid()) {
      79           0 :     O << " Alias:";
      80           0 :     Alias.print(O);
      81             :   }
      82             : 
      83           0 :   if (getKind() == MultiArgClass)
      84           0 :     O << " NumArgs:" << getNumArgs();
      85             : 
      86           0 :   O << ">\n";
      87           0 : }
      88             : 
      89             : #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
      90             : LLVM_DUMP_METHOD void Option::dump() const { print(dbgs()); }
      91             : #endif
      92             : 
      93    46188463 : bool Option::matches(OptSpecifier Opt) const {
      94             :   // Aliases are never considered in matching, look through them.
      95    46188463 :   const Option Alias = getAlias();
      96    46188463 :   if (Alias.isValid())
      97        3412 :     return Alias.matches(Opt);
      98             : 
      99             :   // Check exact match.
     100   138555153 :   if (getID() == Opt.getID())
     101             :     return true;
     102             : 
     103    44534515 :   const Option Group = getGroup();
     104    44534515 :   if (Group.isValid())
     105    27831011 :     return Group.matches(Opt);
     106             :   return false;
     107             : }
     108             : 
     109     1279009 : Arg *Option::accept(const ArgList &Args,
     110             :                     unsigned &Index,
     111             :                     unsigned ArgSize) const {
     112     1279009 :   const Option &UnaliasedOption = getUnaliasedOption();
     113     1279009 :   StringRef Spelling;
     114             :   // If the option was an alias, get the spelling from the unaliased one.
     115     3837027 :   if (getID() == UnaliasedOption.getID()) {
     116     1259732 :     Spelling = StringRef(Args.getArgString(Index), ArgSize);
     117             :   } else {
     118       77108 :     Spelling = Args.MakeArgString(Twine(UnaliasedOption.getPrefix()) +
     119       77108 :                                   Twine(UnaliasedOption.getName()));
     120             :   }
     121             : 
     122     2558018 :   switch (getKind()) {
     123      179268 :   case FlagClass: {
     124      179268 :     if (ArgSize != strlen(Args.getArgString(Index)))
     125             :       return nullptr;
     126             : 
     127      178106 :     Arg *A = new Arg(UnaliasedOption, Spelling, Index++);
     128      356212 :     if (getAliasArgs()) {
     129         468 :       const char *Val = getAliasArgs();
     130        1404 :       while (*Val != '\0') {
     131         468 :         A->getValues().push_back(Val);
     132             : 
     133             :         // Move past the '\0' to the next argument.
     134         468 :         Val += strlen(Val) + 1;
     135             :       }
     136             :     }
     137             : 
     138      356681 :     if (UnaliasedOption.getKind() == JoinedClass && !getAliasArgs())
     139             :       // A Flag alias for a Joined option must provide an argument.
     140           1 :       A->getValues().push_back("");
     141             : 
     142             :     return A;
     143             :   }
     144       50623 :   case JoinedClass: {
     145       50623 :     const char *Value = Args.getArgString(Index) + ArgSize;
     146       50623 :     return new Arg(UnaliasedOption, Spelling, Index++, Value);
     147             :   }
     148        2709 :   case CommaJoinedClass: {
     149             :     // Always matches.
     150        2709 :     const char *Str = Args.getArgString(Index) + ArgSize;
     151        2709 :     Arg *A = new Arg(UnaliasedOption, Spelling, Index++);
     152             : 
     153             :     // Parse out the comma separated values.
     154        2709 :     const char *Prev = Str;
     155       41352 :     for (;; ++Str) {
     156       44061 :       char c = *Str;
     157             : 
     158       44061 :       if (!c || c == ',') {
     159        3147 :         if (Prev != Str) {
     160        3139 :           char *Value = new char[Str - Prev + 1];
     161        3139 :           memcpy(Value, Prev, Str - Prev);
     162        3139 :           Value[Str - Prev] = '\0';
     163        3139 :           A->getValues().push_back(Value);
     164             :         }
     165             : 
     166        3147 :         if (!c)
     167             :           break;
     168             : 
     169         438 :         Prev = Str + 1;
     170             :       }
     171       41352 :     }
     172        2709 :     A->setOwnsValues(true);
     173             : 
     174        2709 :     return A;
     175             :   }
     176       73789 :   case SeparateClass:
     177             :     // Matches iff this is an exact match.
     178             :     // FIXME: Avoid strlen.
     179       73789 :     if (ArgSize != strlen(Args.getArgString(Index)))
     180             :       return nullptr;
     181             : 
     182       73789 :     Index += 2;
     183      147578 :     if (Index > Args.getNumInputArgStrings() ||
     184       73789 :         Args.getArgString(Index - 1) == nullptr)
     185             :       return nullptr;
     186             : 
     187             :     return new Arg(UnaliasedOption, Spelling,
     188       73789 :                    Index - 2, Args.getArgString(Index - 1));
     189           6 :   case MultiArgClass: {
     190             :     // Matches iff this is an exact match.
     191             :     // FIXME: Avoid strlen.
     192           6 :     if (ArgSize != strlen(Args.getArgString(Index)))
     193             :       return nullptr;
     194             : 
     195          12 :     Index += 1 + getNumArgs();
     196           6 :     if (Index > Args.getNumInputArgStrings())
     197             :       return nullptr;
     198             : 
     199          12 :     Arg *A = new Arg(UnaliasedOption, Spelling, Index - 1 - getNumArgs(),
     200          12 :                       Args.getArgString(Index - getNumArgs()));
     201          32 :     for (unsigned i = 1; i != getNumArgs(); ++i)
     202          10 :       A->getValues().push_back(Args.getArgString(Index - getNumArgs() + i));
     203             :     return A;
     204             :   }
     205      971767 :   case JoinedOrSeparateClass: {
     206             :     // If this is not an exact match, it is a joined arg.
     207             :     // FIXME: Avoid strlen.
     208      971767 :     if (ArgSize != strlen(Args.getArgString(Index))) {
     209      604748 :       const char *Value = Args.getArgString(Index) + ArgSize;
     210      604748 :       return new Arg(*this, Spelling, Index++, Value);
     211             :     }
     212             : 
     213             :     // Otherwise it must be separate.
     214      367019 :     Index += 2;
     215      734028 :     if (Index > Args.getNumInputArgStrings() ||
     216      367009 :         Args.getArgString(Index - 1) == nullptr)
     217             :       return nullptr;
     218             : 
     219             :     return new Arg(UnaliasedOption, Spelling,
     220      367009 :                    Index - 2, Args.getArgString(Index - 1));
     221             :   }
     222          23 :   case JoinedAndSeparateClass:
     223             :     // Always matches.
     224          23 :     Index += 2;
     225          46 :     if (Index > Args.getNumInputArgStrings() ||
     226          23 :         Args.getArgString(Index - 1) == nullptr)
     227             :       return nullptr;
     228             : 
     229          23 :     return new Arg(UnaliasedOption, Spelling, Index - 2,
     230          23 :                    Args.getArgString(Index - 2) + ArgSize,
     231          69 :                    Args.getArgString(Index - 1));
     232         810 :   case RemainingArgsClass: {
     233             :     // Matches iff this is an exact match.
     234             :     // FIXME: Avoid strlen.
     235         810 :     if (ArgSize != strlen(Args.getArgString(Index)))
     236             :       return nullptr;
     237         810 :     Arg *A = new Arg(UnaliasedOption, Spelling, Index++);
     238        3324 :     while (Index < Args.getNumInputArgStrings() &&
     239         838 :            Args.getArgString(Index) != nullptr)
     240         838 :       A->getValues().push_back(Args.getArgString(Index++));
     241             :     return A;
     242             :   }
     243          14 :   case RemainingArgsJoinedClass: {
     244          14 :     Arg *A = new Arg(UnaliasedOption, Spelling, Index);
     245          14 :     if (ArgSize != strlen(Args.getArgString(Index))) {
     246             :       // An inexact match means there is a joined arg.
     247           4 :       A->getValues().push_back(Args.getArgString(Index) + ArgSize);
     248             :     }
     249          14 :     Index++;
     250          85 :     while (Index < Args.getNumInputArgStrings() &&
     251          25 :            Args.getArgString(Index) != nullptr)
     252          23 :       A->getValues().push_back(Args.getArgString(Index++));
     253             :     return A;
     254             :   }
     255             : 
     256           0 :   default:
     257           0 :     llvm_unreachable("Invalid option kind!");
     258             :   }
     259             : }

Generated by: LCOV version 1.13